如何通过JAX-RS ExceptionMapper优先化CDI拦截器

时间:2015-11-27 12:38:33

标签: java jax-rs cdi interceptor exceptionmapper

我有一个REST Web服务,使用以下方法管理其事务:

@Inherited
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({METHOD, TYPE, FIELD, PARAMETER})
public @interface TransactionRequired {

}

@Interceptor
@TransactionRequired
public class TransactionRequiredInterceptor {

    @Inject
    private EntityManager entityManager;

    @AroundInvoke
    public Object manageTransaction(InvocationContext ctx) {
        try { 
            ..start transaction..
        }
        catch(Exception e) { 
            ..rollback.. 
        }
    }
}

我也正在映射我的例外:

@Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {

    @Override
    public Response toResponse(RuntimeException exception) {
        .. return some response..
    }

}

问题在于,假设抛出RuntimeException(在事务启动之后),它会被 RuntimeExceptionMapper 立即截获,并且事务永远不会回滚。

这样,我需要一种方法来优先处理 TransactionRequiredInterceptor ..

Obs:使用@Transactional不是一个选项,因为我需要在Tomcat 8上部署。

1 个答案:

答案 0 :(得分:2)

恕我直言,你所要求的是没有意义的。因为您的JAX-RS库不必通过拦截器实现异常映射。

但是你的TransactionRequiredInterceptor仍然可以通过使用finally块来响应异常 - 因为JVM总是(几乎)保证它的执行。

无论如何,我怀疑这是不是一个好主意

首先,更好的方法是使用额外的图层(让我们称之为servicedao)并拦截此类方法。

其次,您可以100%确定您的事务管理实现会有大量的错误。恕我直言(CDI和Tomcat)最好的方法是DeltaSpike,因为它已经为你提供了@Transactional拦截器:org.apache.deltaspike.jpa.api.transaction.Transactional。我亲自使用它取得了巨大的成功。

顺便说一下:由于许多其他有用的功能,你也可以尝试Apache DeltaSpike - 它们可以为你节省很多麻烦。