1

@PostConstruct メソッドでデータベースにアクセスする必要があるため、トランザクションのスコープを制御するために @Singleton SessionBean - EJB 3.1 - で TransactionManager を取得しようとしました。例外が発生した場合、コンテナーは TransactionRolledbackException: setRollbackOnly をシングルトン ポスト コンストラクト メソッド内からスローするため、RollBack を許可できません。

私は JTA DataSource を使用しており、トランザクションの制御をオーバーライドするために @TransactionManagement(TransactionManagementType.BEAN) を定義しています。

@Resource プライベート TransactionManager transactionManager;

「transactionManager.begin();」を実行しようとすると、NullPointerException が返されます。誰もこれを解決する方法を知っていますか?

アップデート:

私が使用しているコードはこれです:

    @Startup
    @Singleton
    @TransactionManagement(TransactionManagementType.BEAN)
    public class RuntimeContextEJB

{

    @EJB
    private RepositoryRecursosExternosFactoryEJB    repositoryRecursosExternosFactoryEJB;

    @EJB
    private MetodologiaIndiceLiquidezFactoryEJB     metodologiaIndiceLiquidezFactoryEJB;

    @EJB
    private FuncaoMatematicaFactoryEJB              funcaoMatematicaFactoryEJB;

    private boolean                                 bootstrapRunning    = false;

    private List<String>                            dadosMercadoMonitorados;

    @PersistenceContext(unitName = "crv-persistence-unit")
    private EntityManager                           entityManager;

    @Resource
    private TransactionManager transactionManager;


    @PostConstruct
    public void init()
    {
        // comentário
        MotorCalculoContext.setupMotorCalculoContext(repositoryRecursosExternosFactoryEJB, metodologiaIndiceLiquidezFactoryEJB,
                funcaoMatematicaFactoryEJB);
        carregaDadosMercadoMonitorados();

    }


    public void sinalizarInicioBootstrap()
    {
        bootstrapRunning = true;
    }


    public void sinalizarTerminoBootstrap()
    {
        bootstrapRunning = false;
    }


    public boolean isBootstrapRunnnig()
    {
        return bootstrapRunning;
    }

    public void carregaDadosMercadoMonitorados()
    {




        try
        {

            transactionManager.begin();

            this.dadosMercadoMonitorados = (List<String>) entityManager
                    .createQuery(
                            "SELECT DISTINCT(p.parametro.codigoDadoMercado) FROM PlanoExecucaoPasso p WHERE p.parametro.codigoDadoMercado <> '' AND p.parametro.codigoDadoMercado <> '0'")
                    .getResultList();
        }
        catch (Exception e)
        {
        }

    }

}

@Resource アノテーションに追加する JNDI アドレスが必要だと思います。これは、WebSphere に固有のものですが、実際には見つかりません。

アップデート:

コンテナ管理のインジェクションで JNDI を使用する理由 ダイレクトインジェクションでヌルポインタ例外が出てしまうので、ex.のように使ってみました。OReilly Enterprise Java Beans 3.1 第 6 版の 305 ページ。

@Resource(mappedName = "java:/TransactionManager")
//mappedName is vendor-specific, and in this case points to an address in JNDI

これを試してみましたが成功しませんでした。

アップデート

WebSphere は私たちの Bean アノテーションを取得していません - 理由を本当に知ることはできません - したがって、アノテーション:

@TransactionManagement(TransactionManagementType.BEAN)

動作していませんでした。そのため、de ejb-jar.xml を編集し、次のコードを追加しました。

<transaction-type>Bean</transaction-type>

そして UserTransaction が機能しました。答えてくれてありがとう。

4

3 に答える 3

2

Bean 管理のトランザクションがある場合は、使用せずjavax.transaction.TransactionManagerに を使用しますjavax.transaction.UserTransaction

そして、UserTransactionインターフェイスのbegin、commit ....などを呼び出します。

回答が更新されました:

1)まず第一に、私が言ったように、使用しないでくださいTransactionManager。使用するUserTransaction

2)オブジェクトのJNDI 名を知りたいUserTransaction場合。ですjava:comp/UserTransaction。ただし、これは、コンポーネントが管理されていない場合にのみ必要です。例:サーブレット、EJB。そのプロセスは、JNDI API を手動で呼び出すことと呼ばれます

3) commit()またはrollback()を提供します。それらのどれも存在しません。

私はあなたのクラスを見ていますが、問題ないようです。

では、どこが問題なのでしょうか? (可能性)

1)クラスが EJB (コンテナ管理) として扱われないため、インジェクションが失敗します。

2) EJB @Startup の前にトランザクション サービスが開始されていないか、開始に失敗しています。

3) persistence.xmlで構成されたJTA データソースがあります。その場合は、次を試してください。

@Resource
private EJBContext context;

userTransaction  = context.getUserTransaction(); 

注:正確な問題を特定するために、完全なスタック トレースとpersistence.xmlも提供してください。

于 2013-04-26T03:09:48.580 に答える
0

UserTransaction を使用して適切に実行され、トランザクションを制御するサンプル コードを次に示します。

@Singleton
@Startup
@TransactionManagement(TransactionManagementType.BEAN) 
public class SampleUT {

Logger logger = Logger.getLogger(SampleUT.class.getName()); 

@Resource
private UserTransaction ut;

@PostConstruct
public void postConstruct()
{
    logger.info("PostConstruct called");

    try {
        ut.begin();
...

取得している NullPointerException は、おそらく、EJB のコンストラクター内で注入されたリソースを使用しようとしたことに関連しています。注入された参照は、EJB のコンストラクターが完了するまで使用できないことに注意してください。そのため、コンストラクター内で注入された参照を使用しようとすると、NullPointerException がスローされます。

于 2013-04-26T04:26:59.977 に答える