2013-08-14 4 views
1

Можно ли исключить исключение из факсимильного компонента CMT (Container Managed Transaction)?Обработка исключений в фазе без учета состояния CMT

Приведенный ниже код не поймает никакого опыта, когда я попробовал его. Если я использую BMT (Bean Managed Transaction), я могу поймать исключение. Но я хочу остаться с CMT.

@Path("books") 
public class BookResource 
{ 

    @EJB 
    private BooksFacade book_facade; 

    private Books local_book; 


    @POST 
    @Consumes({"application/xml", "application/json"}) 
    public Response create(Books entity) 
    { 
     try 
     { 
      book_facade.create(entity); 
     } catch (RuntimeException ex) 
     { 
      System.out.println("Caught database exception"); 
     } 
     return Response.status(Response.Status.CREATED).build(); 
    } 



public class TXCatcher 
{ 

    //@Resource 
    //UserTransaction tx; 
    private final static Logger LOG = Logger.getLogger(TXCatcher.class.getName()); 

    @AroundInvoke 
    public Object beginAndCommit(InvocationContext ic) throws Exception 
    { 
     //ic.proceed(); 
     System.out.println("Invoking method: " + ic.getMethod()); 
     try 
     { 
      //tx.begin(); 
      Object retVal = ic.proceed(); 
      //tx.commit(); 
      return retVal; 
     }catch (RollbackException e) 
     { 
      LOG.log(Level.SEVERE, "-----------------Caught roolback(in interceptor): {0}", e.getCause()); 
      System.out.println("Invoking method: " + ic.getMethod()); 
      throw new CustomEx("Database error"); 
     }catch (RuntimeException e) 
     { 
      LOG.log(Level.SEVERE, "-----------------Caught runtime (in interceptor): {0}", e.getCause()); 
      System.out.println("Invoking method: " + ic.getMethod()); 
      //tx.rollback(); 

      throw new CustomEx("Database error",e.getCause()); 
      //throw new CustomEx("Database error"); 
     } 



     //return ic.proceed(); 


    } 

}

ответ

0

Это зависит от того, какие проблемы вы пытаетесь поймать. Вы можете попробовать явный EntiyManager.flush, но в зависимости от уровня изоляции источника данных некоторые ошибки не могут быть обнаружены до фиксации транзакции, и нет механизма для обнаружения ошибок транзакции для CMT. Если это так, ваш единственный вариант - использовать BMT (даже если вы сказали, что не хотите). Единственное предположение, которое могло бы сделать более приятным, было бы написать перехватчик EJB, который ведет себя аналогично CMT (то есть, вводит UserTransaction в перехватчик и начинает/фиксирует/откатывает в @AroundInvoke).

+0

@ around invoke был моим планом резервного копирования. Я отредактировал код выше, чтобы показать, что он рассматривает другой вопрос. Я раскоментировал транзакционные части, как указано выше, но все равно работает до тех пор, пока мой компонент bookresource аннотируется с помощью TransactionManagement (TransactionManagementType.BEAN). Мой вопрос в том, нужно ли использовать usertransaction? – David031

+0

Вы должны уловить ошибку фиксации транзакции * вне * EJB, как показано в примере JAX-RS, независимо от того, является ли EJB CMT или BMT. Чтобы ответить на другой вопрос: в зависимости от используемого менеджера ресурсов (например, драйвера JDBC), вы можете использовать RMLT (локальная транзакция менеджера ресурсов, например JDBC setAutoCommit (false)), а не XA/глобальная транзакция, но вы теряете все преимущества XA/глобальной транзакции: вы будете ограничены одним БД/ресурсом, вы не получите уведомления о транзакции, вы не сможете использовать JPA с управляемым контейнером и т. д. –

+0

Не могли бы вы расшифровать: «Вы должны уловить ошибку фиксации транзакции вне EJB, как показано в примере JAX-RS». Я попытался использовать перехватчик в компоненте CMT, но я все еще не мог поймать ошибку, например дублирование первичного ключа. Контейнер бросил все исключение клиенту, моя оригинальная проблема. Извините за несколько вопросов, я искал всюду для исправления. – David031

0

Поместив следующую функцию, описанную выше в моей функции создания класса BooksFacade, CMT создал вторую транзакцию в первой транзакции. Когда исключение было выбрано из второй транзакции, мой метод создания класса BookResource мог его поймать. Нет необходимости в BMT.

@Overide 
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
public void create(Books entity) 
{ 
    super.create(entity); 
} 

я отметил, что аннотация работает только при размещении на отдельных методах, путем размещения его на самом классе не сделает разницу.

Смежные вопросы