- PR -

Tomcat5.5上でJTAを使ったトランザクション処理に失敗してしまいます

1
投稿者投稿内容
bk
会議室デビュー日: 2005/11/18
投稿数: 11
投稿日時: 2006-01-19 10:18
Tomcat5.5上で動作するWebアプリケーションを作成しています。
その際、JTA(jotm-2.0.10⇒http://jotm.objectweb.org/)を使用した
トランザクション処理の実装を行なっていますがUserTransactionオブジェクト
がlookup()で取って来れずに困っています。

●環境
WindowsXP
Eclipse3.1 WTP0.7
Tomcat5.5.15

●server.xml
(ContextタグはWTPの機能を使い自動作成したので、Resouceタグを追加しました。)
<Context docBase="・・・" path="/test"
reloadable="true" source="com.ibm.wtp.web.server:test">

<Resource auth="Container" name="jdbc/myDB"
driverClassName="org.postgresql.Driver"
maxActive="20" maxIdle="10" maxWait="-1"
password="" type="javax.sql.DataSource"
url="jdbc:postgresql://localhost:5432/test"
username="postgres"/>

<Resource auth="Container" description="JTA UserTransaction"
name="UserTransaction"
type="javax.transaction.UserTransaction"
factory="org.objectweb.jotm.UserTransactionFactory"
jotm.timeout="60"/>
</Context>

●web.xmlのweb-appタグ内に以下を追加
<resource-env-ref>
<description>DB Connection</description>
<resource-env-ref-name>jdbc/myDB</resource-env-ref-name>
<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
</resource-env-ref>

●呼び出されるサーブレット内での処理

try {
Context ctx = new InitialContext();
DataSource ds =
(DataSource)ctx.lookup("java:comp/env/jdbc/myDB");

UserTransaction ut =
(UserTransaction)ctx.lookup("java:comp/UserTransaction");
//★↑この処理を実行する時にjavax.naming.NamingExceptionが発生!!

ut.begin();

java.sql.Connection con = ds.getConnection();
Statement stmt = con.createStatement();
stmt.executeUpdate("insert into test values(100,'データ')");

ut.rollback();
con.close();

} catch (Exception e) {
e.printStackTrace();
}

●logに出ている例外
javax.naming.NamingException: Cannot create resource instance
at org.apache.naming.factory.TransactionFactory.getObjectInstance(TransactionFactory.java:98)
at javax.naming.spi.NamingManager.getObjectInstance(Unknown Source)
at org.apache.naming.NamingContext.lookup(NamingContext.java:792)
at org.apache.naming.NamingContext.lookup(NamingContext.java:139)
at org.apache.naming.NamingContext.lookup(NamingContext.java:780)
at org.apache.naming.NamingContext.lookup(NamingContext.java:152)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:136)
at javax.naming.InitialContext.lookup(Unknown Source)
at jp.co.hogehoge.test.servlet.FrontController.processRequest(FrontController.java:48)
at jp.co.hogehoge.test.servlet.FrontController.doGet(FrontController.java:103)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:667)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Unknown Source)

●その他の情報
Tomcat5.0.28+JTA(jotm-1.5.3)の環境でserver.xmlを以下のようにした場合は
きちんと上記のソースコードでロールバックされることは確認できました。

<Resource name="jdbc/myDB" auth="Container" type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/myDB">
<parameter>
<name>factory</name>
<value>org.objectweb.jndi.DataSourceFactory</value>
</parameter>
<parameter>
<name>username</name>
<value>postgres</value>
</parameter>
<parameter>
<name>password</name>
<value></value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>org.postgresql.Driver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:postgresql://localhost:5432/test</value>
</parameter>
</ResourceParams>

<Resource name="UserTransaction" auth="Container" type="javax.transaction.UserTransaction"/>
<ResourceParams name="UserTransaction">
<parameter>
<name>factory</name>
<value>org.objectweb.jotm.UserTransactionFactory</value>
</parameter>
<parameter>
<name>jotm.timeout</name>
<value>60</value>
</parameter>
</ResourceParams>


●質問
NamingExceptionなのでserver.xmlのUserTransactionの登録が間違っていると思
うのですが、調べても解決策が見つかりませんでした。
何か心当たりある方がいらっしゃいましたら参考URLだけでも構いませんので、
ご教授の程よろしくお願い致します。
bk
会議室デビュー日: 2005/11/18
投稿数: 11
投稿日時: 2006-02-06 11:38
●修正前
UserTransaction ut =
(UserTransaction)ctx.lookup("java:comp/UserTransaction");

●修正後(lookupメソッドの引数に"emv"を追加)
UserTransaction ut =
(UserTransaction)ctx.lookup("java:comp/env/UserTransaction");

上記のように変更したらjavax.naming.NamingExceptionは出なくなりました。

しかし、まだSQLを流したあとでロールバックをしようとしても、ロールバック処理はされず、DBの中にデータが入ってしまいます。

JOTMのサイトを見てもTomcat5.5に関する記述がなさそうですね。
http://jotm.objectweb.org/

引き続き、同じような現象が起こった方のご意見をお待ちしています。

[ メッセージ編集済み 編集者: bk 編集日時 2006-02-06 11:40 ]
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-02-06 12:41
引用:
しかし、まだSQLを流したあとでロールバックをしようとしても、ロールバック処理はされず、DBの中にデータが入ってしまいます。



通常のTomcatのDataSource(DBCPの実装)ではJTAトランザクションには
参加できないはずなので、JOTM側の実装を使うようにする必要があります。
設定方法はかなり前にやったきりなので、すみませんが覚えてないです。

また、現在のJOTMでは改善されているかもしれませんが、私が試した時は
(1.5.3だったと思います)中核部分に設計レベルの致命的な欠陥があり、
はっきり言って使い物になりませんでした。

同様のプロダクトにTyrexというものもありますが、こちらは開発が停止し、
さらに、最新バージョンも長期間稼働に耐えられるものではなかったです。

実プロジェクトに採用する前に、複数スレッドから負荷をかけるなどの
検証をされることをお勧めします。

引用:
(1.5.3だったと思います)


1.5.3 -> 1.4.3の間違いでした。

[ メッセージ編集済み 編集者: あしゅ 編集日時 2006-02-06 12:46 ]
bk
会議室デビュー日: 2005/11/18
投稿数: 11
投稿日時: 2006-02-06 13:22
引用:

通常のTomcatのDataSource(DBCPの実装)ではJTAトランザクションには
参加できないはずなので、JOTM側の実装を使うようにする必要があります。
設定方法はかなり前にやったきりなので、すみませんが覚えてないです。



情報ありがとうございます。
Tomcat 4.1.18,JOTM 1.4 の例がobjectwebのページにあり、
そこではDataSourceを使用しているように見えます。
これを参考にしていましたがそもそもそれが間違いなのでしょうか?
http://jotm.objectweb.org/current/jotm/doc/howto-tomcat-jotm.html

Tomcat5.0.28では同じソースコードでうまくいっているので、
Tomcat5.5系と異なる部分(=server.xml)の記述がおかしいのかなと思っていました。

(1)Tomcat5.5 + jotm2.0.10 ⇒ うまく行かない
(2)Tomcat5.5 + jotm1.5.3 ⇒ うまく行かない
(3)Tomcat5.0.28 + jotm1.5.3 ⇒ うまく行く

(2)と(3)の違いはserver.xmlの記述だけで、現在(2)で試しています。

JOTM側の実装を使うとのことですが、ちょっとこの辺が理解できていない状態です。
自分で調べてみますので関連サイトがあれば教えていただけると助かります。

引用:

実プロジェクトに採用する前に、複数スレッドから負荷をかけるなどの
検証をされることをお勧めします。



こちらの助言もありがとうございます。
動くようになったらきちんと検証するように致します。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2006-02-06 14:21
引用:

Tomcat 4.1.18,JOTM 1.4 の例がobjectwebのページにあり、
そこではDataSourceを使用しているように見えます。
これを参考にしていましたがそもそもそれが間違いなのでしょうか?
http://jotm.objectweb.org/current/jotm/doc/howto-tomcat-jotm.html


コード:
<ResourceParams name="jdbc/myDB">
  <parameter>
    <name>factory</name>
    <value>org.objectweb.jndi.DataSourceFactory</value>
  </parameter>


リソースファクトリのクラスにJOTMのものを指定してあげれば動くと思いますよ。
bk
会議室デビュー日: 2005/11/18
投稿数: 11
投稿日時: 2006-02-06 15:11
引用:

コード:
<ResourceParams name="jdbc/myDB">
  <parameter>
    <name>factory</name>
    <value>org.objectweb.jndi.DataSourceFactory</value>
  </parameter>


リソースファクトリのクラスにJOTMのものを指定してあげれば動くと思いますよ。



ありがとうございます。
上記のコードにある、org.objectweb.jndi.DataSourceFactory
がJOTMのリーソースファクトリクラスだと思っていたのですが間違っているでしょうか?

これで動かないので間違っているのでしょうけど、他のものが見当たりません。
1

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