3

Tomcat、Atomikos、ActiveMQ、および MySql を使用してトランザクションを機能させようとしています。次の例に従ってください: Tomcat 7 の Atomikos 3.5.2との統合 およびTomcat 7.0.27 の Atomikos 3.7.1との統合 成功しませんでした...

ERROR: com.atomikos.icatch.jta.UserTransactionManager cannot be cast to javax.transaction.TransactionManager
java.lang.ClassCastException: com.atomikos.icatch.jta.UserTransactionManager cannot be cast to javax.transaction.TransactionManager

使用:

  • トムキャット 7.0.29
  • アトミコス 3.7.1
  • アクティブMQ 5.8.0
  • MySQL 5.5.31

$TOMCAT_HOME/lib の下に次の jar をドロップしました

  • atomikos-integration-extension-3.7.1-20120529.jar
  • atomikos-util-3.7.1.jar
  • トランザクション-3.7.1.jar
  • トランザクション-api-3.7.1.jar
  • トランザクション-jdbc-3.7.1.jar
  • トランザクション-jms-3.7.1.jar
  • トランザクション-jta-3.7.1.jar
  • geronimo-jta_1.0.1B_spec-1.0.jar
  • activemq-all-5.8.0.jar
  • mysql-connector-java-5.1.25.jar

ここに transactions.properties の内容があります

com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.automatic_resource_registration=true
com.atomikos.icatch.output_dir=../work/atomikos
com.atomikos.icatch.log_base_dir=../work/atomikos/log
com.atomikos.icatch.enable_logging=true
com.atomikos.icatch.console_log_level=TRACE

context.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Transaction factory="com.atomikos.icatch.jta.UserTransactionFactory" />

    <Resource name="TransactionManager"
          auth="Container"
          type="com.atomikos.icatch.jta.UserTransactionManager"
          factory="org.apache.naming.factory.BeanFactory" />

    <Resource name="UserTransaction"
          auth="Container"
          type="com.atomikos.icatch.jta.UserTransactionImp"
          factory="org.apache.naming.factory.BeanFactory" />                 

    <Resource name="jms/ConnectionFactory"
            auth="Container"
            description="JMS Connection Factory"
            type="com.atomikos.jms.AtomikosConnectionFactoryBean"
            factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory"
            uniqueResourceName="jms/ConnectionFactory"
            xaConnectionFactoryClassName="org.apache.activemq.ActiveMQXAConnectionFactory"
            xaProperties.brokerURL="vm://localhost"
            xaProperties.transportType="1"
            localTransactionMode="true" />

    <Resource name="jms/WsTopic" 
          auth="Container"
          type="org.apache.activemq.command.ActiveMQTopic" 
          factory="org.apache.activemq.jndi.JNDIReferenceFactory"
          physicalName="WS.TOPIC" />

    <Resource name="jms/WsQueue" 
          auth="Container"
          type="org.apache.activemq.command.ActiveMQQueue"
          factory="org.apache.activemq.jndi.JNDIReferenceFactory" 
          physicalName="WS.QUEUE" />


   <!--  MySQL -->
   <Resource name="jdbc/DB"
          auth="Container"
          type="com.atomikos.jdbc.AtomikosDataSourceBean"
          factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory"
          uniqueResourceName="jdbc/DB"
          minPoolSize="5"
          maxPoolSize="10"
          testQuery="SELECT 1 FROM DUAL"             
          xaDataSourceClassName="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"
          xaProperties.databaseName="db"
          xaProperties.serverName="localhost"
          xaProperties.port="3306"
          xaProperties.user="user"
          xaProperties.password="password"
          xaProperties.url="jdbc:mysql://localhost:3306/db"
          xaProperties.pinGlobalTxToPhysicalConnection="true"
          xaProperties.autoReconnect="true"
          xaProperties.autoReconnectForConnectionPools="true"
          xaProperties.autoReconnectForPools="true" />
</Context>

関連する Java コード:

import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
...

Hashtable<String, String> hashTable = new Hashtable<String, String>();
try {
    Context ctx = new InitialContext(hashTable);
    ctx = (Context) jndiContext.lookup("java:comp/env");

    TransactionManager transactionManager = (TransactionManager) ctx.lookup("TransactionManager");
} catch (Exception e) {
    e.printStackTrace();
}

私は何を間違っていますか?

編集:

$TOMCAT_HOME/lib から activemq-all-5.8.0.jar を削除した後、元のエラーを回避できましたが、次のようになりました。

com.atomikos.jms.AtomikosJMSException: Error in proxy
at com.atomikos.jms.AtomikosJMSException.throwAtomikosJMSException(AtomikosJMSException.java:54)
at com.atomikos.jms.ConsumerProducerSupport.handleException(ConsumerProducerSupport.java:61)
at com.atomikos.jms.AtomikosJmsMessageConsumerProxy.receive(AtomikosJmsMessageConsumerProxy.java:73)
at com.atomikos.jms.AtomikosJmsMessageConsumerProxy.receive(AtomikosJmsMessageConsumerProxy.java:137)
...
at java.lang.Thread.run(Thread.java:619)
Caused by: com.atomikos.jms.AtomikosTransactionRequiredJMSException: The JMS session you are using requires a JTA transaction context for the calling thread and none was found.
Please correct your code to do one of the following: 
1. start a JTA transaction if you want your JMS operations to be subject to JTA commit/rollback, or
2. increase the maxPoolSize of the AtomikosConnectionFactoryBean to avoid transaction timeout while waiting for a connection, or
3. create a non-transacted session and do session acknowledgment yourself, or
4. set localTransactionMode to true so connection-level commit/rollback are enabled.
    at com.atomikos.jms.AtomikosTransactionRequiredJMSException.throwAtomikosTransactionRequiredJMSException(AtomikosTransactionRequiredJMSException.java:38)
    at com.atomikos.jms.ConsumerProducerSupport.enlist(ConsumerProducerSupport.java:107)
    at com.atomikos.jms.AtomikosJmsMessageConsumerProxy.receive(AtomikosJmsMessageConsumerProxy.java:70)
    ... 5 more
4

1 に答える 1

4

Tomcat は複数のクラスローダーを使用します。それらの定義、それがどのように機能するか、優先されるもの (bootstrap、system、webapp、common)を参照してください。に加えて、WAR ファイル内にgeronimo-jta_1.0.1B_spec-1.0.jarand/orを配置したと仮定します。クラスが異なるクラスローダーによって複数回ロードされるため、これにより問題が発生する可能性があります。クラスが同じ名前であっても、別のクラスローダーによってロードされた場合、キャストは失敗します。transactions-jta-3.7.1.jarwebapp.war/WEB-INF/lib/$TOMCAT_HOME/lib/javax.transaction.TransactionManager

  1. によって実装された で定義されたコンテナー全体のTransactionManagerリソースを Tomcat が初期化するときに、最初に共通のクラスローダー ($TOMCAT_HOME/lib/*.jar)でロードされます。(現時点では、Tomcat はwebappクラスローダーを使用しません。)context.xmlcom.atomikos.icatch.jta.UserTransactionManager

  2. javax.transaction.TransactionManagerWeb アプリケーションでクラスを使用すると、WAR ファイル内のフォルダーにある JAR ファイルのコピーからwebapp class-loader でロードされます。webapp.war/WEB-INF/lib/

javax.transaction.TransactionManagerクラスを含む JAR ファイルを から削除してwebapp.war/WEB-INF/lib/、アプリケーションを再デプロイしてみてください。

または、これらの JAR ファイルをCLASSPATHシステム変数にリストして、Tomcat で優先されるシステム クラスローダーによってこれらのクラスがロードされるようにします。

于 2013-06-24T18:45:22.680 に答える