Как сделать сессионные компоненты без сохранения состояния транзакциями?
Как получить в бине сеанса без состояния информацию о том, что транзакцию необходимо откатить? Например, у меня есть EJB без сохранения состояния, который обновляет LuceneIndex с некоторыми бизнес-данными. Метод вызывается в транзакции с несколькими вызовами EJB. Когда некоторые из более поздних EJB-компонентов откатывают транзакцию, как я могу получить информацию об этой проблеме, чтобы иметь возможность откатить уже написанную запись LuceneIndex?
2 ответа
Вы можете сделать это, вставив ссылку на текущий EJBContext, а затем запросив его:
@Stateless
public class LuceneDriver {
@Resource
private EJBContext ejbContext;
public void performLuceneStuff(...) {
try {
...
// update lucene data
...
// update some business data
...
} catch (BusinessException e) {
if (ejbContext.getRollbackOnly()) {
// rollback lucene changes
}
}
}
...
}
Если сессионный EJB не является транзакционным, вы не сможете выполнить откат в случае сбоя. Это из-за отсутствия информации о состоянии EJB сеансов без сохранения состояния.
Одним из решений этой проблемы является использование сессионного компонента @Stateful, который реализует javax.ejb.SessionSynchronization
интерфейс. Этот интерфейс позволяет вам реагировать на откат.
Другое решение заключается в работе с пользовательскими записями EventLog, записанными основной транзакцией через JPA. С этими записями eventLog другие EJB сеанса без сохранения состояния могут проверить, существуют ли новые записи EventLog и могут ли они реагировать на него. Если транзакция была отменена, диспетчер транзакций также удалит незафиксированные записи EventLog. Так что это решение для соединения нетранзакционных функциональных возможностей с транзакцией на основе контейнера JPA. См. Вопрос: Как реагировать на принятие или откат транзакции EJB3?