javajax-rscdiinterceptorexceptionmapper

How to priorize CDI Interceptor over JAX-RS ExceptionMapper


I have a REST webservice that manage its transactions using the following approach:

@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.. 
        }
    }
}

And I am also mapping my exceptions like this:

@Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {

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

}

The issue is that when, lets say, an RuntimeException is thrown (after transaction being started), it is immediatelly intercepted by the RuntimeExceptionMapper and the transaction is never rollbacked.

Being so, I need a way to priorize the TransactionRequiredInterceptor..

Obs: Using @Transactional is not an option since I need to deploy on Tomcat 8.


Solution

  • IMHO what you are asking doesn't make sense. Because your JAX-RS library doesn't have to implement an exception mapping via interceptors.

    But still your TransactionRequiredInterceptor can respond to the exception by using a finally block - because JVM always (almost) guarantee its execution.

    Anyway, I doubt if it's a good idea.

    Firstly, a much better way, would be to have additional layer (let's call it service or dao) and intercept such class methods.

    Secondly, you can be 100% sure that your implementation of the transaction management will have plethora of bugs. IMHO in your case (CDI and Tomcat) the best way to go is DeltaSpike because it already gives you such @Transactional interceptor: org.apache.deltaspike.jpa.api.transaction.Transactional. I use it personally with a great success.

    BTW: you can try Apache DeltaSpike also due to many other useful features - they can save you many headaches.