CDI 拦截器和事务传播

CDI Interceptor and transaction propagation

我想在 EJB 方法的调用周围添加一个 CDI 拦截器。 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.怎么可能?

谢谢!

拦截器在同一个事务上下文中。在 EJB 世界中有两种异常:

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

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

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