Hi

There currently are two issues floating around dealing with the question of 
returning more information than just null from the Adaptable.adaptTo(Class) 
method: https://issues.apache.org/jira/browse/SLING-3714 and 
https://issues.apache.org/jira/browse/SLING-3709. I think these requests 
warrant some discussion on the list.

Background: adaptTo can be implemented by Adaptable implementations themselves 
or, by extending from SlingAdaptable, they may defer to an AdapterMananager. 
AdapterManager itself is extended by AdapterFactory services. All these 
interfaces define an adaptTo method. All these methods return null if adaption 
is not possible and don't declare or document to throw an exception.

While not explicitly documented as such, the intention is and was that adaptTo 
never throws on the grounds that adaption may fail which is considered a valid 
result and thus exceptions are not to be expected and handled.

Hence all implementations of the methods generally 
catch-and-log-but-don't-throw. Interestingly SlingAdaptable.adaptTo and 
AdapterManagerImpl.getAdapter don't catch — so any RuntimeException thrown from 
an AdapterFactory would be forwarded.

Having said this there are options available:

(1) Add support for a new Result<?> class. We would probably implement this in 
the AdapterManager.getAdapter implementation explicitly handling this case 
because it would entail catching the adaptTo/getAdapter calls to get the 
exception (the Result.getError should return Throwable probably not Error)

Use would be limited to new AdapterFactory implementations throwing 
RuntimeExcpetion. For Sling Models this would be the case.

(2) Add a new adaptToOrThrow method, which is declared to throw a 
RuntimeException and never return null: Either it can adapt or it throws. This 
would require a new interface Adaptable2 (probably) to not break existing 
Adaptable implementations. The SlingAdaptable base class would implement the 
new method of course, probably something like this:

> SlingAdaptable implements Adaptable2 {
>    …
>    public <AdapterType> AdapterType adaptToOrThrow(Class<AdapterType> type) {
>        AdapterType result = this.adaptTo(type);
>        if (result != null) {
>            return result;
>        }
>        throw new CannotAdaptException(…);
>    }
> }
> 

Use is problematic because you would have to know whether you can call the new 
method: So instead of an null check you now have an instanceof check … Except 
for the Resource interface which would be extended to extend from Adaptable2 as 
well.

(3) Document, that Adaptable.adaptTo may throw a RuntimeException.

The problem here is, that this may conceptually break existing callers of 
Adaptable.adaptTo which don't expect an exception at all — presumably this is a 
minor nuisance because technically a RuntimeException may always be thrown.

Regards
Felix

Reply via email to