XAテスト移植

JBoss+MySQL用のシンプルなインテグレーションテストは既に以前作成してあったのだけれども,今回WebLogic+MySQL用に作ったものの方がよりシンプルかつテスト範囲が広いため,WebLogic用に作ったテストコードをJBoss用に移植した.

移植といってもよくみたらJNDIプロパティとデータソース名を変えるだけ(しかも定数クラスに切り出してあるので・・・)で至極簡単だったわけだが.

XDoclet用のタグもCMPとかを結局使わないことになったので"@ejb"から始まるやつのみ.

ところで,WebLogicは最後まで悩ませてくれる.以下のコードをEJB内で実行するとWebLogicではサーバ再起動するまで該当データソースが使えなくなる.

InitialContext ctx = new InitialContext(Const.JNDI_PROPS);
DataSource ds = (DataSource) ctx.lookup(Const.XADS_JNDI);
Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
DataSource ds2 = (DataSource) ctx.lookup(Const.XADS_JNDI2);
Connection conn2 = ds2.getConnection();
Statement stmt2 = conn2.createStatement();

UserTransaction utx = this.sc.getUserTransaction();
utx.begin();
stmt.executeUpdate("INSERT INTO xasimpletest VALUES (100)");
stmt2.executeUpdate("INSERT INTO xasimpletest2 VALUES (200)");
ResultSet rs = stmt2.executeQuery("SELECT connection_id()");
rs.next();
int connectionId = rs.getInt(1);
stmt2.executeUpdate("KILL " + connectionId);
Thread.sleep(100);
try {
    utx.commit();
} catch (Exception e) {
    // expected
}

conn.close();
// for windows
try {
    stmt2.executeUpdate("SELECT 1");
} catch (Exception e) {
    // ignore
}
conn2.close();
ctx.close();

テストなので意図的にDBへの接続をKILLコマンドで切っているわけだが,運用時には何らかの原因により(例えばタイムアウトやネットワーク障害によって)接続が切れた場合,WebLogicでは管理者がサーバを再起動させるまでアプリが動かなくなるんじゃないかな,もしかして.

JBossの場合はこのコードを実行した後も引き続き別のコードからデータソースを利用できるのに.

また爆弾発言しちゃいますよ.

WebLogicってJCA実装しょぼい?

XAテスト解決

一通りのテストに成功.やれやれ.

感想:WebLogicは当初想像していた以上に扱いにくいプロダクトだったよ.上っ面はいいんだけど中身がちょっとJBossよりもクオリティ低いかも.

記念ログあげ.

163 Query       XA START 0x0000db50835b7f28edb9,0x4d7953514c20584120436f6e6e656374696f6e20506f6f6c,0xbea1
165 Query       XA START 0x0000db50835b7f28edb9,0x4d7953514c20584120436f6e6e656374696f6e20506f6f6c32,0xbea1
163 Query       INSERT INTO xasimpletest (number) VALUES (100)
165 Query       INSERT INTO xasimpletest (number) VALUES (110)
165 Query       SELECT connection_id()
165 Query       KILL 165
163 Query       XA END 0x0000db50835b7f28edb9,0x4d7953514c20584120436f6e6e656374696f6e20506f6f6c,0xbea1
163 Query       XA PREPARE 0x0000db50835b7f28edb9,0x4d7953514c20584120436f6e6e656374696f6e20506f6f6c,0xbea1
163 Query       XA ROLLBACK 0x0000db50835b7f28edb9,0x4d7953514c20584120436f6e6e656374696f6e20506f6f6c,0xbea1

UserTransaction.commit()中にどこかのXAResourceでエラーが発生した場合,全体がロールバックされるテスト時のログ(MySQL一般クエリログ).今回はこの間のJBossXAユニットテストと同じように2つのXAResourceをどっちもMySQLにしてやった.WebLogicJMS意味不明だし.

changeUser() そして 問題解決(?)

getXADataSouceした時に以前のConnector/JはchangeUserコマンドを発行していた.changeUserが発行されるとautocommitとかの接続後に設定した内容が初期化される.

つまりこの仕様に立てば,AppServerはサーバ起動時のコネクションプーリング作成の際だけでなく,グローバルトランザクションを発行する際にも再度setAutocommit(false)を呼ばなければならないはずだった.

しかしながらWebLogic側ではそのような呼び出しを行う実装になっておらず,ここに想定通りにテストが通らない原因の1つがあった.

この問題はConnector/Jの未リリース最新版を使うことで回避が可能.さっそくこれを入手して試してみたところ,commit-rollbackともにうまく機能した.

(この問題を回避しないと,XAであるにも関わらずDB接続の実体がautocommitモードに戻ってしまっている(MySQLのデフォルト)のでrollbackメソッドをコンテナ側が読んでもDB側はコミット済みという状況になる)

相変わらずWebLogicJMSは信じがたい動きをしているが,WebLogicMySQL XAコネクション 2本でのXAテストに変え,この問題をクリアしたことでやっと前進できるような状態になった.このまま上手く行ってくれると良いが.