主に Jboss Forge によって生成されたアプリケーションで Jboss 7.1.1 を使用していますが、すべてのドメイン関連コードのリポジトリ レイヤーを追加しました。
データベースの状態を初期化するスタートアップ Bean を作成しようとしていました。そのために既存のリポジトリを使用したいと思います。
私のリポジトリにはすべて、拡張された PersistenceContext が注入されています。@ConversationScoped @Stateful Bean である View Bean からこれらを使用します。拡張コンテキストを使用することで、エンティティは会話中に管理されたままになります。
最初にこれを試しました:
@Startup
@Singleton
public class ConfigBean {
@Inject
private StatusRepository statusRepository;
@Inject
private ZipCode zipCodeRepository;
@PostConstruct
public void createData() {
statusRepository.add(new Status("NEW"));
zipCodeRepository.add(new ZipCode("82738"));
}
}
Example repository:
@Stateful
public class ZipCodeRepository {
@PersistenceContext(PersistenceContextType.EXTENDED)
private EntityManger em;
public void add(ZipCode zipCode) {
em.persist(zipCode);
}
....
}
これにより、アプリケーションの起動時に javax.ejb.EJBTransactionRolledbackException がスローされ、次のメッセージが表示されます。
JBAS011437: SFSB 呼び出しコール スタックで拡張永続コンテキストが見つかりましたが、トランザクションに関連付けられたトランザクション コンテキストが既にあるため、使用できません。これは、アプリケーション コードを変更して、拡張永続コンテキストまたはトランザクション コンテキストを削除することで回避できます。JPA 仕様 2.0 セクション 7.6.3.1 を参照してください。
これについての適切な説明を見つけるのに苦労しましたが、実際には、EJB とその注入はプロキシによって処理されるため、PersistenceContext の注入と伝播はすべて自動的に処理されると考えました。私は間違っていたと思います。
ただし、この考えの過程で、次のことを試しました。
@Startup
@Singleton
public class ConfigBean {
@Inject
private SetupBean setupBean;
@PostConstruct
public void createData() {
setupBean.createData();
}
@Stateful
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public static class SetupBean {
@Inject
private StatusRepository statusRepository;
@Inject
private ZipCode zipCodeRepository;
public void createData() {
statusRepository.add(new Status("NEW"));
zipCodeRepository.add(new ZipCode("82738"));
}
}
}
これでうまくいきます。私がしたことは、Singleton Bean の静的内部クラスである Stateful SessionBean にコードをラップすることだけでした。
誰もこの行動を理解していますか?現在はすべてが機能していますが、なぜこのように機能するのかについては、まだ少し疎遠になっているからです。