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.