- PR -

■EJB Transaction■SessionBean でのCMTについて

1
投稿者投稿内容
あさぬみ
会議室デビュー日: 2004/05/27
投稿数: 5
投稿日時: 2004-05-27 16:33
お疲れ様です.
SessionBean(Stateless)でのEJBコンテナによるトランザクション制御が
上手く動作せず困っています.
Transaction制御を行ないたいSessionBeanのメソッドは以下のような感じで、
”JDBCコネクションを使用して実行されたDBのUPDATE処理を、EJBコンテナ側でロールバック
させたいが、DB処理がロールバックされず、UPDATE処理がDBにコミットされてしまう”
という状況です.

public void execute()
{
try
{
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("Oracle9i");
Connection con = ds.getConnection();

//SQL によるUpdate
Statement stmt = con.createStatement();
sql = "UPDATE customer_tbl set name = 'hoge' where id = 1";
stmt.executeUpdate(sql);

// データベースのクローズ
stmt.close();
con.close();

//setRollbackOnlyによる強制ロールバック命令
sessionContext.setRollbackOnly();
}catch(Exception e){}
}

その他備考ですが、
@ 環境:Weblogic8.1j + Oracle9i + Solaris9
A JDBCコネクションはDataSource経由で非XAのものを取得
B Stateless SessionBean,Transaction TypeはContainerに設定(以下にejb-jar.xml)

<ejb-jar >
<enterprise-beans>
<session >
<ejb-name>OracleTest</ejb-name>
<home>test.ejb.OracleTestHome</home>
<remote>test.ejb.OracleTest</remote>
<local-home>test.ejb.OracleTestLocalHome</local-home>
<local>test.ejb.OracleTestLocal</local>
<ejb-class>test.ejb.OracleTestBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>

<assembly-descriptor >
<container-transaction>
<method>
<ejb-name>OracleTest</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>

また、別のアプローチとして以下のようなパターンも試しましたが、いずれもロールバック
されませんでした.
@ setRollbackOnly()を呼ぶタイミングで、throw new TransactionRolledbackLocalException();
を行なったが、ロールバックはされなかった.
A TransactionTypeをBeanに設定、DB処理後UserTransactionによるrollback()を
行なったが、ロールバックは確認できなかった.

お知恵のある方、問題点を指摘していただけませんでしょうか.
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-05-27 17:41
コード:
stmt.close(); 
con.close(); 

//setRollbackOnlyによる強制ロールバック命令 
sessionContext.setRollbackOnly(); 
}catch(Exception e){} 
} 


本題と直接関係ありませんが、Statement,ResultSet,Connection 等のクローズは finallyブロックにて確実に閉じましょう。リソースのリークを招く可能性があります。WLS ならあるていど閉じてくれますが頼りすぎては行けません。
また、catch(Exception e){} ではなにか例外が発生してもわかりませんね。

さらに、BEA に問い合わせは行ったでしょうか?もしサポート契約しているなら・・。
あさぬみ
会議室デビュー日: 2004/05/27
投稿数: 5
投稿日時: 2004-05-27 18:12
レスポンス有り難うございます.インギさんのおっしゃる通り、正しくは
}catch(Exception e){
e.pritstacTrace();
}finally{
// データベースのクローズ
stmt.close();
con.close();
}

この様にするべきですね.サンプルなので手を抜いてしまいました.
EJBコンテナにおけるTransaction制御についての不明点は主に以下の二点です.
@ CMTに参加するConnectionを明示的にコンテナに伝える必要はないのか
A 使用するConnectionは非XAのものでよいのか(LocalTxの場合)

WebLogicを使用して他に必要な設定等ありましたら、ご指摘願います.
評価版を使用しているので、サポートは無いんです(無念)
ASA
会議室デビュー日: 2004/05/27
投稿数: 6
投稿日時: 2004-05-27 18:44
あさぬみさん、こんにちは。

WLS8.1は使った事がないのでわかりませんが、6.1ではトランザクションデータソースを使用しないとコンテナ管理のトランザクションは使えなかったです。

では。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-05-27 19:30
> CMTに参加するConnectionを明示的にコンテナに伝える必要はないのか ?
トランザクション属性を Required にしていれば自動的にトランザクションが開始されますのでコーディングによるトランザクション境界の設定は不要です。
> 使用するConnectionは非XAのものでよいのか(LocalTxの場合)
トランザクションに参加するデータソースが複数なければ非XAのドライバで結構です。ただし、ASAさんのご指摘の通りトランザクショナルである必要があります。
つまりデータソース作成時に "グローバルトランザクションを受け付ける" にチェックを入れないといけません。
チェックを入れていない場合は直接 Connection#begin()/commit()/rollback() しないといけません。
#いっぱんてきにそれをローカルトランザクションと言います。

トランザクションについての統計は
[ドメイン->サーバ->サーバ名->モニタ->JTA(->リソース別トランザクションのモニタ)]
にて確認できます。トランザクション処理がちゃんと行われているか見てみましょう。

[ メッセージ編集済み 編集者: インギ 編集日時 2004-05-27 19:31 ]
あさぬみ
会議室デビュー日: 2004/05/27
投稿数: 5
投稿日時: 2004-05-27 20:27
レスありがとうございます。
解決しました.原因はご指摘の通り、
”データソース作成時に "グローバルトランザクションを受け付ける" にチェックを入れる”
のを忘れていた為でした.

対象とするDBが1つだったので、グローバルトランザクションの機能は必要ないと思いチェックを外してしまったのが敗因でしたね.

本当に有り難うございました.
1

スキルアップ/キャリアアップ(JOB@IT)