Hi Vincent,

Your suggestion seems reasonable. I've applied this changed to SVN trunk
(only). It is slightly different from your patch. Let me know if it works
for you:

    public Resource createResource(Request request, Response response) {
        Resource result = null;

        if (getTargetClass() != null) {
            try {
                        [...]
            } catch (InvocationTargetException e) {
                if (e.getCause() instanceof Error) {
                    throw (Error) e.getCause();
                } else {
                    getLogger() [...]
                }
            } catch (Exception e) {
                    getLogger() [...]
            }
        }

Best regards,
Jerome  

> -----Message d'origine-----
> De : news [mailto:[EMAIL PROTECTED] De la part de Vincent
> Envoyé : jeudi 13 septembre 2007 00:41
> À : [email protected]
> Objet : Unchecked exceptions in Resource constructors
> 
> 
> Hello,
> 
> 
> My application throws unchecked exceptions; I derived 
> StatusService so that 
> I can decide what status code and representation to send to 
> the client.
> 
> It works as expected except when the exception is thrown from 
> a resource
> constructor. 
> Because  Finder.createResource uses reflection to call my 
> resource constructor,
>  the unchecked exception gets wrapped into an 
> InvocationTargerException; 
>  this (checked) exception  is  caught by the method's 'catch 
> (Exception e)' 
> block, which logs  a  message and returns null:
> 
> 
> public Resource createResource(Request request, Response response) {
>   Resource result = null;
>   if (getTargetClass() != null) {
>     try {
>       [...]
>       result = constructor.newInstance(getContext(), 
> request,response);
>       [...]
>      } catch (Exception e) {
>        getLogger().log(...);
>      }
>   }
>   return result;
> }
> 
> 
> My unchecked exception has been swallowed- and now, 
> Finder.handle assumes it's
>  a 404:
> 
> public void handle(Request request, Response response) {
> [...]                 
>   Resource target = findTarget(request, response);
>   if (!response.getStatus().equals(Status.SUCCESS_OK)) {
>     // Probably during the instantiation of the target resource, or
>     // earlier the status was changed from the default one. Don't go
>     // further.
>   } else if (target == null) {
>    // If the currrent status is a success but we couldn't find the
>    // target resource for the request's resource URI, then we set
>   // the response status to 404 (Not Found).
>   response.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
>  }
> [...]
> }
> 
> My solution is to provide my own Finder, catch 
> InvocationTargetException, 
> and rethrow the cause (it it's an error):
> 
> class MyFinder extends Finder {
> public Resource createResource(Request request, Response response) {
>   Resource result = null;
>   Error error  = null;
>     try {  
>       [...]
>       try {
>          [...]
>       } catch (NoSuchMethodException nsme) {
>       [...]
>       }                       }
>       catch(InvocationTargetException e){
>         if (e.getCause() instanceof Error){
>           error =(Error)  e.getCause();
>         }
>       }
>     } catch (Exception e) {
>       getLogger().log([...]);
>     }
>  }
>  // rethrow the Error that was wrapped in InvocationTargetException
>  if (error != null){
>     throw error;
>  }
>  return result;
> }
> 
> 
> The alternative would by to catch Error in all my resource 
> constructors, 
> set the response status to SERVER_ERROR, and rethrow the error. Not
> very compelling.
> 
> Do you see the current behavior as a design flaw? I agree 
> that resource
> constructor should not throw check exceptions because we know they're
> created by reflection, but we should let unchecked exceptions 
> bubble up. 
> 
> 
> 
> -Vincent.

Reply via email to