CDI拦截器和事务传播

时间:2015-05-13 10:03:24

标签: java cdi

我想添加一个EJB方法的CDI Interceptor arround调用。 EJB是一个商业服务@Stateless,其中注入了CDI DAO。

@Stateless
class MyService {

    @Inject
    private DAO myDAO;

    @Workflow
    @TransactionAttribute(TransactionAttributeType.REQUIRED)    
    public void doStuff(MyData data) {
    //doing stuff 
    myDAO.edit(data);
    //doing others DAO stuff
    }    
}

虽然默认情况下EJB是事务性的,但所有DAO调用都在同一个事务中,但现在我想在这个方法中添加一个拦截器。

@InterceptorBinding
@Inherited
@Target({ TYPE, METHOD })
@Retention(RUNTIME)
@Documented
public @interface Workflow {}

@Workflow
@Interceptor
public class WorkflowInterceptor {

    @Inject
    private transient Logger logger;

    @Inject
    private DAO myDAO;

    @AroundInvoke
    public Object manage(final InvocationContext ic) throws Exception {
        ic.proceed();
        //do other stuff with DAO
        throw new ServiceException("OMG Error!");
    }

}

我希望WorkflowInterceptor中的DAO调用与MyService处于同一个事务中。怎么可能呢?

谢谢!

1 个答案:

答案 0 :(得分:1)

Interceptor位于同一个事务上下文中。在EJB世界中有两种例外:

  • 系统异常(通常是运行时异常,但并非总是如此)
  • 应用程序异常(通常是用户定义的[已检查]异常,并且存在于方法签名中 - 例如void a() thows B。)

事务总是在系统异常时自动回滚。但是,程序员有责任处理应用程序异常上的事务回滚。另一个主要区别是系统异常(与应用程序异常不同)由容器包装在EJBException中,然后重新抛出。

您还可以通过使用@ApplicationException对用户进行注释,将用户定义为RuntimeExceptionApplicationException。在那里,您可以指定是否要自动回滚事务,或者是否应继承@ApplicationException行为