Skip to content

Instantly share code, notes, and snippets.

@danbev
Created September 17, 2012 13:50
Show Gist options
  • Save danbev/3737360 to your computer and use it in GitHub Desktop.
Save danbev/3737360 to your computer and use it in GitHub Desktop.
AeroGear-Controller: Exception Handling

AeorGear-Controller Exception Handling

This gist has been updated (see history for previous discussions) and aims to discuss solutions to AEROGEAR-426 "General/fall-back error page on Controller".

aerogear-controller branch
aerogear-controller-demo branch

Adding an on method for exceptions

Example of specifying a single exception:

    @Override
    public void configuration() throws Exception {
        route()
                .on(DeloreanException.class)
                .to(ExceptionHandler.class).errorPage();
        route()
                .from("/")
                .on(RequestMethod.GET)
                .to(Home.class).index();
    }

Test

Example of specifying multiple exceptions:

    @Override
    public void configuration() throws Exception {
        route()
                .on(DeloreanException.class, SomeOtherException.class)
                .to(ExceptionHandler.class).errorPage();
        route()
                .from("/")
                .on(RequestMethod.GET)
                .to(Home.class).index();
    }

It's possible for the errorPage to take an Exception as a parameter, for example if some action like logging should take place:

@Override
    public void configuration() throws Exception {
        route()
                .on(DeloreanException.class, SomeOtherException.class)
                .to(ExceptionHandler.class).errorPage(param(Exception.class));
        route()
                .from("/")
                .on(RequestMethod.GET)
                .to(Home.class).index();
    }

Test

In the above examples the errorPage would be resolved to WEB-INF/ExceptionHandler/errorPage.jsp.

API

To support multiple exceptions the on method of RouteBuilder looks like this:

    TargetEndpoint on(Class<? extends Throwable> exception, Class<?>... exceptions);

Now, this is somewhat ugly and the second parameter is not typesafe (though runtime check is performed) but was the cleanest solution I could think of with regard to ease of use, and without polluting the API.
The issue here was to avoid compiler warnings about using varargs in combination with generics (Class) from client code (with @Safevarargs in Java7 which should be able to make this typesafe at compile time). Hopefully, with the first parameter being typed this will make it understandable for users and obvious that the classes following the first parameter should also be of the same type.

What are your thoughts on this?

@qmx
Copy link

qmx commented Sep 17, 2012

@danbev I was thinking in something much more simple. As you can see into the JIRA

route().on(MyException.class).to(Home.class).anotherPage();

Note the absence of from - the idea is having a catchall route.

having onException for individual routes makes it way more complicated than it should be IMO. if you really need to have fine control over the outcome, put this on the controller - the idea is that the controller handles only forward routes (mostly) and your code handles the "responses"

@abstractj
Copy link

+1 for just on instead of onException.

I like the idea of do not have suffixes, great point to start Daniel

@danbev
Copy link
Author

danbev commented Sep 17, 2012

@qmx Ah my mistake, I missed that the from() method was missing in the route in the Jira description :(
So, have I understood this correctly by saying that the below on(Exception) would handle any MyException thrown from any route declared within the same configuration() method?

route().on(MyException.class).to(Home.class).errorPage();
route().from("/").on(RequestMethod.GET).to(Home.class).index();
...

Should this support a single Exception of should it be possible to specify multiple?

the idea is that the controller handles only forward routes (mostly) and your code handles the "responses"

I see, I'll fix this and the other issues.
Out of curiosity, the use case I was thinking about with regard to sending a response, was a form being sent with invalid data, and that it might be useful to send a response rather than forwarding. Would such a use case be handled in some other way?

@abstractj on it is :)

Thx

@danbev
Copy link
Author

danbev commented Sep 18, 2012

@qmx @abstractj I've taken another shot at this and hopefully this is a littler closer to the goal.

As discussed in the earlier comments a catch-all exception route could be added like this:

    route().on(IllegalArgumentException.class).to(SampleController.class).error(param(Exception.class));
    route()
           .from("/home")
           .on(RequestMethod.GET)
           .to(SampleController.class).throwsException();

In this case the Home class would have a method named error which takes an exception as a parameter.
The parameter would be optional and perhaps we could support passing an Object[] of the params sent with the original request (if any that is)?

DefaultRoute will catch any exception and see if there is a route that can handle the exception in question:

       } catch (Exception e) {
            final Throwable rootCause = Throwables.getRootCause(e);
            final Route errorRoute = routes.routeFor(rootCause);
            if (errorRoute != null) {
                final Object result = invokeErrorTarget(errorRoute, rootCause, params);
                forwardError(new View(viewResolver.resolveViewPathFor(errorRoute), result), request, response);
            } else {
                throw new ServletException(e);
            }
        }

The above would then forward the result, if any, from the error method to the resolved view. The exception is set as an attribute in the forwardError method and could be accessed in jsp page like this:

<%@page pageEncoding="UTF-8" %>
<html>
    <body>
        <p>General error handling page:</p>
        <p>${exception}</p>
    </body>
</html>

What are your thoughts on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment