Как сказал
Нам нужно, чтобы интерфейсный компонент Seam ( не-EJB ) вызывал несколько методов DAO (EJB) и заключал их в одну транзакцию
Но
Наши транзакции обрабатываются контейнером - также называется транзакцией, управляемой контейнером (контейнер заботится о вызове метода begin и commit , используемого каждой базовой транзакцией администратора ресурсов)
Первая проблема заключается в том, что у вас есть сценарий, когда не-EJB вызывает несколько DAO, каждый из которых - EJB. Вы могли бы подумать о
@Name("nonEjbComponent")
public class NonEjbComponent {
private @In DaoEjbComponent daoEjbComponent;
private @In OtherDaoEjbComponent otherDaoEjbComponent;
private @In AnotherDaoEjbComponent anotherDaoEjbComponent;
private @In UserTransaction userTransation;
public void wrapperAllOfThem() {
userTransation.begin();
daoEjbComponent.save(someEntity);
otherDaoEjbComponent.update(otherEntity);
anotherDaoEjbComponent.delete(anotherEntity);
userTransation.commit();
}
}
Но спецификация Java EE 3.0 гласит:
Корпоративный компонент с разграничением транзакций, управляемых компонентом или контейнером должен быть компонентом сеанса или компонентом, управляемым сообщениями .
Таким образом, вы не можете использовать сценарий выше. И поскольку все ваши DAO используют транзакции, управляемые контейнером, спецификация Java EE не позволяет вам использовать транзакцию, управляемую контейнером и управляемую компонентом одновременно
Итак, решение
Обернуть все DAO в сессионный компонент EJB без состояния , транзакция которого управляется контейнером . Он будет вести себя как компонент делегата
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Name("wrapperStateless")
public class WrapperStatelessImpl implements WrapperStateless {
private @In DaoEjbComponent daoEjbComponent;
private @In OtherDaoEjbComponent otherDaoEjbComponent;
private @In AnotherDaoEjbComponent anotherDaoEjbComponent;
public void wrapperAllOfThem() {
daoEjbComponent.save(someEntity);
otherDaoEjbComponent.update(otherEntity);
anotherDaoEjbComponent.delete(anotherEntity);
}
}
И внутри вашего не-EJB компонента используйте
@Name("nonEjbComponent")
public class NonEjbComponent {
private @In WrapperStateless wrapperStateless;
public void wrapperAllOfThem() {
wrapperStateless.wrapperAllOfThem();
}
}