2015-11-27 8 views
0

отдыхает WebService, что управлять его операцией, используя следующий подход:Как Предпочитать CDI перехватчик над JAX-RS ExceptionMapper

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

+0

Похоже, вы перехватываете весь метод ресурсов. Я предполагаю, что вы вызываете EM внутри метода ресурсов. Почему бы вам не добавить слой DAO и перехватить вызовы DAO. –

ответ

2

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

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

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

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

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

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

+1

Спасибо, что помогло мне :) –

+0

Кроме того, CDI уже предоставляет перехватчик '' '@ Transactional''' только для этого – maress

+0

@maress Nope. '@ javax.transaction.Transactional' - это просто аннотация. Сам CDI не предоставляет вам какой-либо перехватчик, обрабатывающий эту аннотацию, - таким образом, он будет пропускаться молча :-) '@ Transactional' учитывается из коробки только тогда, когда транзакции EJB3 присутствуют в пути к классам (например, на сервере Java EE). –