Hi Adam,
I agree that the class inheritance approach to categorizing exceptions
(in this case, a web exception) has its limitations, but unfortunately
this is the simplest way to deal with it due to the Java language
approach.
There are a few alternatives to the one you proposed, all of them
(including the annotation based one) might require the addition of a
(not so cute) if to the error handling catch block. I will try to
generalize the proposal:
a) Create an annotation with status code and so on (as you mentioned)
In this case error handling would be limited to setting a custom
status code and/or message. We can enhance it even further if instead
of doing so, the annotation had a processor hint, for instance:
@WebProblem(processor = MyExceptionHandler.class)
class MyException ...{
}
class MyExceptionHandler implements Handle<ME> {
// inject what you want and use it here
public void handle(ME ex) {
}
}
You still need to check with an if:
catch(Exception e) {
if(e.getClass().andItsParents().isAnnotationPresent(WebProblem.class0 {
provider.for(e.getClass().andItsParents().getAnnotation(WebProblem.class).processor).handle();
}
}
A default processor behaviour could interpret an annotation as you suggested:
@StatusInfo(...)
@WebProblem
class MyException ... {
}
b) Create a WebProblem interface with a method getProcessor() and let
your exception classes inherit from it:
@WebProblem(processor = MyExceptionHandler.class)
class MyException {
}
class MyExceptionHandler implements Handle<ME> {
// inject what you want and use it here
public void handle(ME ex) {
}
}
Again, it does not avoid the extra if clause:
if(WebProblem.class.canBeAttributedFrom(e.getClass()) {
((WebProblem) e).getProcessor().handle();
}
This second approach is actually type safe. I believe the annotation
one is not (you can say the processor is a class that does not
implement the Processor interface).
What do you think?
Guilherme Silveira
Caelum | Ensino e Inovação
http://www.caelum.com.br/
On Mon, Nov 22, 2010 at 11:36 AM, Adam Walczak <me_at_adamwalczak.info> wrote:
> Hello,
>
> First of all I would like to thank all the Jersey developers for the
> JAX-RS effort. This API is really a pleasure to work with, especially
> with Glassfish's EJB integration.
>
> I liked it so much that I decided to use it not just for the REST API
> but as a whole web application framework. With a small team of
> developer we created a whole reservation portal in Poland based on
> Jersey with it's JSP and EJB integration. It was a nice ride buy it
> required some add-ons to get there. Now after the project is in
> production I have some time to suggest those add-ons to the Jersey
> community and probably re-implement them if accepted.
>
> The first one in line is the exception mapping. The
> WebApplicationException way seamed something really unacceptable to
> us. We already had EJB services implemented and our own exception
> hierarchy. Redefining that hierarchy to use WebApplicationException
> would add a dependency to JAX-RS in our logic which just didn't seam
> right. Also writing ale additional layer of EJB to pack our exceptions
> to a WebApplicationException seamed as some unnecessary effort.
>
> So we made the following decisions:
> 1. By default all exceptions should be outputted in the response so
> that the calling application (AJAX client for example) can do the
> appropriate user interaction.
> 2. Everything beyond that default should be defined by annotating the
> exception class.
>
> To accomplish this first we created a @WebThrowable annotation to set
> the response code of and exception. This works like this:
>
> @WebThrowable(statusCode=403)
> public class AuthorizationException extends RuntimeException { ...
>
> Then we created a class implementing ExceptionMapper<Throwable> which
> build the Response in the following way:
>
> return Response
> .status(status) // taken from WebThrowable or
> WebApplicationException or 500 by default
> .type(mt) // depending on a configuration property plain
> text, xml or json
> .entity(e) // the exception
> .build();
>
> And finally we added a class implementing MessageBodyWriter<Throwable>
> which depending on the configured media type prints the exception like
> this:
> - plain text - just prints the localizedMessage
> - json - prints to JSON using JAXB
> - xml - prints to XML using JAXB
>
> I would like to ask the community would this type of functionality be
> welcome in the official jersey release ?
> Should it be implemented in the core library and activated by a
> configuration property ?
> Or should it be done in and library add-on which tries to expand
> jersey to a whole web application framework ?
>
> --
> Adam Walczak
> www.adamwalczak.info
> +48 604 188 992
>