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