言われるように
フロントエンドのSeamコンポーネント(非EJB)で複数のDAO(EJB)メソッドを呼び出し、それらすべてを1つのトランザクションでラップする必要があります。
だが
私たちのトランザクションはコンテナによって処理されます-コンテナ管理トランザクションとも呼ばれます(コンテナは、基になる各リソースマネージャトランザクションによって使用される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();
}
}
しかし、JavaEE仕様3.0には次のように記載されています。
Bean管理またはコンテナ管理のトランザクション境界を持つエンタープライズBeanは、セッションBeanまたはメッセージ駆動型Beanである必要があります。
したがって、上記のシナリオを使用することはできません。また、すべてのDAOがコンテナー管理トランザクションを使用しているため、Java EE仕様では、コンテナー管理トランザクションとBean管理トランザクションを同時に使用することはできません。
したがって、解決策は
トランザクションがコンテナ管理されているEJBステートレスセッションBeanですべてのDAOをラップします。デリゲートコンポーネントのように動作します
@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();
}
}