异常可能发生在EJB层的服务端和网页层,甚至独立的客户端。在第一种情况下,异常停留在同一VM中,也可能被传送到网页层。这儿就是我们要安装的顶层异常处理器的地方。
在后一种情况下,异常发生在EJB容器的边缘并且通过RMI连接传递到客户端。必须注意不要传送任何属于服务端类的异常(如来自对象关系映射框架这类的)到客户端。而由EJB异常处理器通过使用SerializableException作为中介来处理这个问题。在客户端,顶层的Swing异常处理器捕获其他未处理的错误并采取相应措施。
异常处理框架
在Rampart框架中异常处理器是一个实现了ExceptionHandler接口的类。这个接口仅有一个包含两个参数(待处理的Throwable和当前的Thread)的方法。方便起见,框架提供了包含基本的实现类ExceptionHandlerBase,他辨别Throwable并将其代理给RuntimeException, Error, Throwable和Rampart框架的Unrecoverable的特定的抽象方法来处理。子类提供这些方法的实现并区别处理。
下面的类图显示了异常处理器的层次和三个缺省的异常处理器。

许多人认为SUN应该在每应用的基础上给J2EE框架内置插入所有容器的钩子。这样就允许自定义错误处理方案、安全及更多可安装的功能,而不需要依赖特定厂商的方案和框架。不幸地是,SUN并没有在EJB规范中提供这样的机制。既然如此,我们只有拿出AOP这个强有力的工具来增加异常处理。我们选择的AspectWerkz框架,可以如下使用方面:
public class EJBExceptionHandler implements AroundAdvice {
private ExceptionHandler handler;
public EJBExceptionHandler() {
handler = ConfigHelper.getEJBExceptionHandler();
}
public Object invoke(JoinPoint joinPoint) throws Throwable {
Log log = LogFactory.getLog(joinPoint.getEnclosingStaticJoinPoint().getClass().getName());
log.debug("EJB Exception Handler bean context aspect!!");
try {
return joinPoint.proceed();
} catch (RuntimeException e) {
handler.handle(Thread.currentThread(), e);
} catch (Error e) {
handler.handle(Thread.currentThread(), e);
}
return null;
}
}
实际的处理器是通过ConfigHelper类来配置和获取的。如果RuntimeException 或者Error在业务逻辑处理过程被抛出时,处理器就会被请求处理了。
