S2 2.4.18以降でS2JMS

S2JMSのアウトバウンド通信で受信を繰り返していたら、なぜか10回受信したところで止まってしまう現象に遭遇。

この10回という数字はなんだろう?と思っていろいろやってみたところ、コネクションプールのデフォルト値らしいことが判明。さらによ〜く調べてみるとプールからコネクションを取れずにずっと空きまちになっている感じでした。さらにさらによ〜〜く調べてみるとプールにコネクションを戻せていないようでした。


前は普通に使えてたのにな・・・って思ったところで閃きました。S2のバージョンをS2JMS(というかS2JCA)が依存している2.4.17にしてみようと。


結果、やはり2.4.17にしたら普通に使えました。で、移行ガイドを見たら

S2JTA において,Synchronization#afterCompletion(int) メソッドは完全にトランザクションコンテキスト外で呼び出されるようになりました (JTA の仕様です).afterCompletion() 内で TransactionManager#getTransaction() を呼び出すと,従来は完了した Transaction を取得できましたが,rc4 からは null が返されます.

これかー。でも2.4.18以降が使いたいなー。という訳でS2JCAをいじってみました。

org.seasar.jca.outbound.policy.AbstractTransactionBoundedPoolingPolicy

Synchronizationを実装するのをやめて以下のような内部クラスを作ります。

public class SynchronizationImpl implements Synchronization {

    /** トランザクション */
    protected final Transaction tx;

    /**
     * インスタンスを構築します。
     * 
     * @param tx
     *            トランザクション
     */
    public SynchronizationImpl(final Transaction tx) {
        this.tx = tx;
    }

    public final void beforeCompletion() {
    }

    public void afterCompletion(final int status) {
        releaseContext(tx);
    }
}

releaseContextはトランザクションをもらうように変更します。

protected void releaseContext(Transaction tx) {
    final ManagedConnectionPool<Object> pool = pools.get(tx);
    if (pool != null) {
        pool.close();
    }
}

org.seasar.jca.outbound.policy.LocalTransactionBoundedPoolingPolicy

org.seasar.jca.outbound.policy.XATransactionBoundedPoolingPolicy

associateTxの

tx.registerSynchronization(this);

の部分を

TransactionUtil.registerSynchronization(tx, new SynchronizationImpl(tx));

あるいは

tx.registerSynchronization(new SynchronizationImpl(tx));

に変更する。


まぁほとんどorg.seasar.extension.dbcp.impl.ConnectionPoolImplのコピペですが、とりあえずこれで動くようになりました。