У меня проблемы с управлением транзакциями в EJB3.0. Что я хочу сделать, так это записать ошибку в базу данных на случай возникновения исключения.
Для этой цели у меня есть 2 компонента без сохранения состояния: Bean A
и Bean B
.
Бин A выполняет следующие действия:
- сохранить что-нибудь
- вызов
Bean B
для регистрации ошибки при необходимости
На шаге 1 сохранение в основном выполняется методом EntityManager#merge(-)
.
На шаге 2 я поместил следующие строки вверху Bean B
:
@Stateless(name = "ErrorLogDAO", mappedName = "ErrorLogDAO")
@Remote
@Local
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class ErrorLogDAOBean {...}
Однако, когда в методе сохранения возникает исключение, я его перехватываю, а затем вручную вызываю метод ctx.setRollBackOnly()
, и после этого я вызываю ErrorLogDAOBean
, который вставляет журнал ошибок в БД. Но журнал ошибок не вставляется, и я получаю следующую ошибку:
javax.transaction.TransactionRolledbackException: EJB Exception::
weblogic.transaction.internal.AppSetRollbackOnlyException at
weblogic.transaction.internal.TransactionImpl.setRollbackOnly (TransactionImpl.java:551)
в
weblogic.transaction.internal.TransactionManagerImpl.setRollbackOnly (TransactionManagerImpl.java:319)
в
weblogic.transaction.internal.TransactionManagerImpl.setRollbackOnly (TransactionManagerImpl.java:312)
в
org.eclipse.persistence.transaction.JTATransactionController.markTransactionForRollback_impl (JTATransactionController.java:145)
в
org.eclipse.persistence.transaction.AbstractTransactionController.markTransactionForRollback (AbstractTransactionController.java:196)
в
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.rollbackTransaction (UnitOfWorkImpl.java:4486)
в
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase (UnitOfWorkImpl.java:1351)
в
org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase (RepeatableWriteUnitOfWork.java:468)
в
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet (UnitOfWorkImpl.java:1439)
в
org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges (RepeatableWriteUnitOfWork.java:316)
в
org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush (EntityManagerImpl.java:527)
....
Я хорошо знаком с логикой управления транзакциями, и, основываясь на приведенном выше коде, я предположил, что это покрыто, но, похоже, нет.
Есть идеи?
UPDATE
Bean A код:
@TransactionManagement(value = TransactionManagementType.CONTAINER)
@TransactionAttribute(value = REQUIRED)
public class WMServiceBOBean {
public void saveInBeanA {
int errorCode = save();
if (errorCode != SUCCESS)
{
ClassX.logError();
ctx.setRollbackOnly();
return errorCode;
}
}
}
Код X класса:
public class classX
{
...
public void logError()
{
ErrorLog e = new ErrorLog;
BeanB beanB = //Local lookup of Bean B
beanB.insertErrorLog (e);
}
...
}
BEAN B код:
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class ErrorLogDAOBean
{
...
public void insertErrorLog (ErrorLog e)
{
merge (e);
}
...
}