Вложенная транзакция в ejb sessionbean - транзакция, управляемая bean-компонентом
У меня есть следующий код, который сохраняет пользователя и отправляет сообщение JMS. В настоящее время я заворачиваю saveUserSendMessage
с UserTransaction. Когда транзакция вложена, я получаю исключение в ejb. Что я делаю ниже, чтобы сделать возможной вложенную транзакцию?
@Resource(mappedName = "java:/JmsXA")
private static QueueConnectionFactory queueConnectionFactory;
@Resource(mappedName = "EjbQueueJndi")
private static Queue queueProp;
@PersistenceContext(unitName = "ejbPersistanceunit")
private EntityManager em;
@Resource
UserTransaction ut;
@Override
public boolean saveUserSendMessage(String name, String email, int age,
boolean arg3) throws Exception {
UserTransaction xact = ut;
xact.begin();
saveUser(name, email, age);
sendMessage("Successfully saved the user");
try {
if (arg3)
throw new Exception("Unsuccessfull");
xact.commit();
} catch (Exception e) {
xact.rollback();
throw e;
}
return true;
}
@Override
public boolean saveUser(String name, String email, int age)
throws Exception {
try {
ut.begin();
UserEntity ue = new UserEntity();
ue.setAge(age);
ue.setEmail(email);
ue.setName(name);
em.persist(ue);
ut.commit();
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return true;
}
Исключение я получаю:
15:51:04,127 ERROR [STDERR] javax.transaction.NotSupportedException: BaseTransaction.checkTransactionState - [com.arjuna
.ats.internal.jta.transaction.arjunacore.alreadyassociated] [com.arjuna.ats.internal.jta.transaction.arjunacore.alreadya
ssociated] thread is already associated with a transaction!
1 ответ
Java EE не поддерживает вложенные транзакции. Единственное, что он поддерживает, - это приостановка транзакции, выполнение несвязанной транзакции и возобновление первой транзакции.
Для этого вам понадобится вызвать другой EJB-компонент, использующий атрибут транзакции requireNew. Обратите внимание, что внутренняя транзакция может завершиться, даже если квитанция сообщения откатывается, что означает, что в случае сбоя механизма обмена сообщениями вторая транзакция может быть выполнена снова. В качестве альтернативы вы можете изменить EJB на использование транзакций, управляемых компонентами, что будет иметь аналогичный эффект.
Вы уверены, что действительно хотите это сделать? Вероятно, лучше всего выполнить логику внутри транзакции, управляемой контейнером.