Как расставить приоритеты CDI Interceptor над JAX-RS ExceptionMapper

У меня есть веб-сервис REST, который управляет своими транзакциями, используя следующий подход:

@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 ответ

Решение

ИМХО, что вы спрашиваете, не имеет смысла. Потому что ваша библиотека JAX-RS не должна реализовывать отображение исключений через перехватчики.

Но все же ваш TransactionRequiredInterceptor может ответить на исключение, используя finally блок - потому что JVM всегда (почти) гарантирует его выполнение.

В любом случае, я сомневаюсь, что это хорошая идея.

Во-первых, гораздо лучше было бы иметь дополнительный слой (назовем его service или же dao) и перехватывать такие методы класса.

Во-вторых, вы можете быть на 100% уверены, что ваша реализация управления транзакциями будет иметь множество ошибок. ИМХО в вашем случае (CDI и Tomcat) лучший путь - это DeltaSpike, потому что он уже дает вам такой @Transactional перехватчик: org.apache.deltaspike.jpa.api.transaction.Transactional, Я использую это лично с большим успехом.

Кстати: вы можете попробовать Apache DeltaSpike также благодаря множеству других полезных функций - они могут избавить вас от многих головных болей.

Другие вопросы по тегам