|
Seam Catch provides a simple, lightweight infrastructure based on Java 6 contexts and dependency injection (CDI) that helps a developer establish a unified and robust exception handling process.
Think of Seam Catch as catching and processing any and all exceptions as you direct in your code. Throwable is the base exception class in Java. It represents all exceptions; all are extensions of it.
When an exception is thrown, it's likely wrapped in another. The collection of exceptions in its entirety is called an exception stack trace. The outermost isn't usually the most important (or, it's misleading). Hence, Seam Catch doesn't merely pass the trace directly to the exception handlers (that you code and mark with @Handles). Instead, it unwraps the stack trace and treats the root exception as the primary one.
So, for example, Seam Catch first handles, a BatchUpdateException or a DataTruncation, rather than the more vague SqlException that will wrap them.
It calls any handler designated as catching the most significant exception, then works its way through the stack trace notifying designated handlers until a handlers marks the exception as "handled". A handler might instead tell Seam Catch to rethrow the exception outside the Seam Catch infrastructure, a which point exception handling returns to the grosser Java exception handling framework. For more on this, see Seam Catch documentation, sections 3.3. Exception stack trace processing and 3.4. Exception handler ordering.
There are two:
CaughtException has several methods that aid in flow control. Their names identify their function well, I think:
ExceptionStack contains information about the exception causes relative to the current exception and is the source of the execution classes the invoked handlers are matched against. Call getExceptionStack() on the CaughtException object.
More on this is covered in 3.5. APIs for exception information and flow control.
Seam Catch can not only catch checked events, it can intervene in how they are handled including...
...because the interface is annotative and minimal.
void executeHandlers( @Observes @Any ExceptionToCatch payload, final BeanManager bm ) { ... }
(Don't put too much stock or significance in this example. I don't grok it well enough to explain it yet.)
public class MyBaseApplication { @Inject private Event< ExceptionToCatch > catchEvent; void service() { try { ... } catch( MyBaseApplicationException e ) { // adding own basic integration... this.catchEvent.fire( new ExceptionToCatch( e ) ); } } }
See 3.2.2. @Handles for a step-by-step on how the standard exception handler(s) work.
/** * Here we implement all the standard and back-up extension handlers. These have utter flexibility * not only to handle the exception, but to decide in what order, whether to pass it on to another * handler, rewrite the trace, etc. */ @HandlesExceptions public class MyStandardExceptionHandlers { public void rollbackTransaction( @Handles CaughtException< PersistenceException > event, UserTransaction tx ) { try { tx.rollback(); } catch( SystemException e ) { ... } event.handled(); } public void logExceptions( @Handles( during = TraversalMode.BREADTH_FIRST, precedence = Precedence.HIGH ) CaughtException< Throwable > event, Logger log ) { log.error( "Exception caught: " + event.getException().getMessages() ); } public void endConversation( @Handles CaughtException< MyBaseApplicationException > event, Logger conv ) { if( !conv.isTransient() ) conv.end(); } }
...because it consists of only two JARs, not the entire Seam framework.
Also, however, a JAR from the Java EE 6 Platform is required:
/* * JBoss, Home of Professional Open Source Copyright 2011, Red Hat, Inc., and individual * contributors by the @authors tag. See the copyright.txt in the distribution for a full listing of * individual contributors. Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in * writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. */ package org.jboss.seam.exception.example.basic.servlet.navigation; import java.io.IOException; import javax.enterprise.event.Event; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jboss.seam.exception.control.ExceptionToCatch; /** * Navigation rules based on Seam Servlet events. * * @author Jason Porter */ @WebServlet( name = "NavigationServlet", urlPatterns = "/Navigation/*" ) public class NavigationServlet extends HttpServlet { private static final long serialVersionUID = 1L; private enum NavigationEnum { NULLPOINTEREXCEPTION( new NullPointerException( "Null pointer thrown" ) ), ASSERTIONERROR ( new AssertionError( "Assertion Error" ) ), IOEXCEPTION ( new IOException( "IOException" ) ), WRAPPEDILLEGALARG ( new IllegalStateException( "Wrapping IllegalStateException", new IllegalArgumentException( "Inner IAE" ) ) ), INDEX_JSP ( new NullPointerException( "index.jsp" ) ) // INDEX_JSP ( new IllegalStateException( "Wrapping IllegalStateException", // new IllegalArgumentException( "index.jsp" ) ) ; private final Throwable exception; private NavigationEnum( final Throwable e ) { this.exception = e; } public Throwable getException() { return exception; } } @Inject private Event< ExceptionToCatch > catchEvent; @Override protected void service( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException { final String uri = req.getRequestURI(); try // http://localhost:9090/NavigationServlet/Navigation/index.jsp { String desc = uri.substring( uri.lastIndexOf( "/" ) + 1 ) .toUpperCase() .replace( '.', '_' ); final NavigationEnum nav = NavigationEnum.valueOf( desc ); throw new ServletException( nav.getException() ); // wrapping because we don't want to // try / catch and we can't add // the throws list } catch( IllegalArgumentException e ) { this.catchEvent.fire( new ExceptionToCatch( e ) ); // If there is no catch integration, // this is how to add basic // integration yourself } } }