Как распространить пользовательскую транзакцию на стороне клиента в сессионный компонент без сохранения состояния, используя BMT
Этот сценарий с использованием CMT работает:
Сессионный компонент без сохранения состояния с CMT, один метод аннотирован
@TransactionAttribute(TransactionAttributeType.MANDATORY)
, В рамках этого метода запись записывается в RDBMS с использованием источника данных XA и простого JDBC.Автономный клиент (отдельная JVM, приложение Java из командной строки) получает
UserTransaction
с сервера приложений (путем поиска JNDI) запускает транзакцию и вызывает EJB.Если клиент фиксирует
UserTransaction
запись заносится в базу данных.- Если клиент откатывает
UserTransaction
запись не записана в базу данных. В файлах журнала PostgreSql можно увидеть подготовленную транзакцию с помощью BEGIN и COMMIT или ROLLBACK.
Если клиент не запускает транзакцию до вызова EJB,
javax.ejb.EJBTransactionRequiredException
брошен (как и ожидалось,TransactionAttributeType.MANDATORY
).
Теперь я переключаюсь с CMT на BMT
Опять же, если клиент не запускает транзакцию до вызова EJB,
javax.ejb.EJBTransactionRequiredException
выбрасывается (как и ожидалось, TransactionAttributeType.MANDATORY).Если я позвоню
sessionContext.getUserTransaction().getStatus()
всегда сообщаетStatus.STATUS_NO_TRANSACTION
,Запись всегда записывается в базу данных, если клиент вызывает
commit
или жеrollback
,В файлах журнала PostgreSql нет готовых транзакций, просто команды вставки.
Источник EJB:
@Remote(DemoIfc.class)
@Stateless(name = "DemoBmt")
@TransactionManagement(TransactionManagementType.BEAN)
public class DemoBmt implements DemoIfc {
@Resource
private SessionContext sessionContext;
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public String ping(final String s) throws SystemException {
try {
System.out.println("TX: status: "
+ this.sessionContext.getUserTransaction().getStatus());
} catch (Exception e) {
System.out.println("TX: status: " + e.getMessage());
}
try {
writeIntoDb();
if (s.startsWith("crash")) {
throw new SystemException("Simulated crash");
}
return s.toUpperCase();
} catch (NamingException e) {
throw new SystemException(e.getMessage());
} catch (SQLException e) {
throw new SystemException(e.getMessage());
}
}
}
Источник клиента:
final UserTransaction ut = (UserTransaction) initialContext
.lookup("UserTransaction");
try {
ut.begin();
System.out.println(demo.ping("crash: DemoBmt with UT"));
ut.commit();
} catch (Exception ex) {
System.out.println("Expected rollback");
ut.rollback();
}
Я использую JBoss 6.0.0 final.
Как правильно распространять пользовательскую транзакцию на стороне клиента в EJB с помощью BMT?
1 ответ
Бины BMT не могут участвовать в существующей транзакции
13.6.1. Разграничение управляемых компонентом транзакций
Контейнер должен управлять вызовами клиента для экземпляра корпоративного компонента с разграничением транзакций, управляемых компонентом, следующим образом. Когда клиент вызывает бизнес-метод через одно из клиентских представлений корпоративного компонента, контейнер приостанавливает любую транзакцию, которая может быть связана с клиентским запросом....