Seam Catch: ‘more than simply logic in your catch block.’
JAXenter speaks to Seam Catch module lead Jason Porter, on Seam’s ‘Next Generation Exception Handling.’
Jason Porter has been involved in software development since the mid 90’s. He’s worked in e-Government (since before the term was coined), financial, and consumer markets. He has contributed to many open source projects including flyspray (a bug tracking system in PHP), Seam, Weld, and Gradle. His software interests include Java EE, Ruby, and Groovy. He is the father of two daughters and one son and enjoys spending time with his family. He lives in the Salt Lake valley in Utah.
The first release of the Seam Catch module has been made available. JAXenter speaks to module lead Jason Porter on the 3.0.0.Alpha1 release, and what developers can expect from future releases of this module….
JAXenter: What is the Seam Catch module?
Jason Porter: Seam Catch is the exception handling module in Seam 3, however it’s not only for use within the Seam branded modules. It is a portable CDI extension and could be used with any compliant CDI environment either with or without the rest of Seam 3.
We’re calling it Next Generation Exception Handling. It’s more than simply logic in your catch block. Typically what you find in applications is e.printStackTrace() at worst, or very simple messages to the user at best — which are a copy and paste of a few lines of code. Rarely do you find anything really being done with an exception.
Part of this I believe is because the developer doesn’t always know what to do with them, and also because the Java language really doesn’t give developers many tools to deal with exceptions. Of course some exceptions really can’t be handled well. For example, what do you do if you’re trying to write to a file and the hard drive crashes or space is exhausted part way through? Java will throw an IOException, but what do you do with that, wrap and rethrow, send the user to an error page, log it, swallow it (yikes!)? None of these are great options, and everyone is going to do it differently.
A much better approach is to give registered handlers a chance to deal with it in a unified way. That’s the approach Catch offers. You forward the exception on to a handler chain, the handlers are filtered based on the exception type and qualifiers and the handlers can do what they do best.
The other scenario Catch addresses is when an unhandled exception bubbles out to the top layer of a web request. Consider your options today. You have to define an exception mapping in web.xml. You have two options, send an HTTP status code or forward to an error page. That’s almost as useless as presenting the server error page. What if you need to unwrap an exception to find the root cause? You don’t have that choice, but you do with Catch! The Catch integrations trap these exceptions and forward them onto the Catch handler chain, funneling them back to that unified approach. But Catch doesn’t just dump the original exception onto the handlers. It intelligently unwraps the exception, treating the root cause as the primary exception. For example, in an Enterpise Application, all exceptions are wrapped inside an EJBException. You don’t know what the actual exception is! Catch will unwrap that root cause and feed it to the handlers until a handler flags the exception event as handled. The integration may then proceed with instructions provided by the handler, such as to send an error response or redirect the user somewhere appropriate.
Seam Catch also strives to give you more information about the exception by allowing you to inject parts of your application into the handler and give you some idea what the user was doing when the exception occurred.
JAXenter: An initial release of the Seam Catch module was recently made available – what functionality is included in 3.0.0.Alpha1?
Jason Porter: Alpha1, of course is the first release and really doesn’t contain much with regards to integration with various frameworks. It’s the ground work to tie into these frameworks and create exception handlers. In the examples there is a very simple JAX-RS application which demonstrates a possible way to tie Catch into JAX-RS. Alpha1 is still very functional and I encourage people to try it out and give feedback. Expect to see Alpha2 very shortly with minor API changes (mostly renaming of classes / methods) and the ability to use exception handlers that were created programmatically through Seam Config or other means of creating CDI Beans.
JAXenter: How does this module aid the exception handling process?
Jason Porter: First, and I think foremost, all of the exception handling logic is in one place, and it doesn’t even have to be inside the application code base. There could be a company wide jar of exception handlers that is included in the application and used. Second, because exception handlers are similar to CDI observers other objects (state of your application) can be used to really determine what to do with an exception. Things such as which page of a web app the user is on, role of the user, action being performed, etc. could make a difference as to what is done with an exception. Catch and CDI allow all of these things to be present to help the developer make a decision about the exception.
JAXenter: How do Catch handlers differ from CDI Observers?
Jason Porter: First, it’s important to recognize how they are similar. Handlers were designed to follow the syntax and semantics of observe methods, with some special purpose exceptions, which I’ll mention below. We chose this design so that they will be immediately familiar to those studying or well-versed in CDI. This also allows us to keep the strengths of observers. Handlers can still use decorators and interceptors, just like observers, they can be qualified like observers. For example, if you have a PersistenceException raised in your application, you can have a specific handler for instances of this exception within a servlet request, a JAX-RS request, a JSF request, etc! This hasn’t been available before and is very nice to have.
There are, however, a few key differences between observers and
1) Handlers are ordered. With CDI Observers there’s no guarantee as to the ordering of observers and when they’ll be invoked.
2) Handling can be aborted or terminated early without having to throw a new exception in the handler and
3) handlers currently (will probably be changing in the near future to some degree) must be in a very specific format: must be public methods of a class annotated with @HandlesExceptions, first parameter must be a parametrized type of CaughtException and annotated with @Handles.
JAXenter: What functionality is planned for future releases?
Jason Porter: We would definitely like to get
some integrations done with various
frameworks, notably JAX-RS, JSF, Servlets and even basic Java SE. Also we plan to give the developer the ability to filter stack traces when logging exceptions. Does it really matter that we went through ten levels of native Java method calls or internal application server calls to get to the exception? Typically not. We also plan on creating some default handlers such as logging, UI messaging, transaction rollback, etc. Personally I’d like to explore the idea of a save point. The idea being an exception occurred during a block of code but we can recover from that by changing some of the state which is available for that code block and re-execute that block of code successfully. This may be a little ambitious, but it would definitely be helpful.
Another very cool idea, which is actually possible today, is to create and send a JMS message within your handler and essentially handle your exception asynchronously! Granted this won’t work for everything, but simple things like logging could be implemented this way.