Атомикос, Tomcat, JTA java.lang.ClassCastException
Попытка заставить транзакции работать с использованием 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
С помощью:
- Tomcat 7.0.29
- Атомикос 3.7.1
- ActiveMQ 5.8.0
- MySQL 5.5.31
Отбросил следующие jar-файлы в $TOMCAT_HOME/lib
- atomikos-интеграция-разгибания 3.7.1-20120529.jar
- atomikos-Util-3.7.1.jar
- Операции-3.7.1.jar
- Операции-апи-3.7.1.jar
- Операции-3.7.1.jar-JDBC
- Операции-JMS-3.7.1.jar
- Операции-JTA-3.7.1.jar
- Джеронимо-jta_1.0.1B_spec-1.0.jar
- ActiveMQ-все-5.8.0.jar
- MySQL-разъем-Java-5.1.25.jar
Вот содержимое транзакций. Свойства
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();
}
Что я делаю неправильно?
РЕДАКТИРОВАТЬ:
После удаления activemq-all-5.8.0.jar из $TOMCAT_HOME/lib я смог обойти исходную ошибку, но теперь я получаю:
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
1 ответ
Tomcat использует несколько загрузчиков классов. Посмотрите их определения, как это работает и что имеет приоритет (начальная загрузка, система, веб-приложение, общие). Я полагаю, вы разместили geronimo-jta_1.0.1B_spec-1.0.jar
и / или transactions-jta-3.7.1.jar
внутри файла WAR webapp.war/WEB-INF/lib/
в дополнение к $TOMCAT_HOME/lib/
, Это может вызвать проблемы, как javax.transaction.TransactionManager
класс будет загружен несколько раз разными загрузчиками классов. Даже если класс имеет одно и то же имя, если он загружен разными загрузчиками классов, приведение не будет выполнено.
Сначала он загружается общим загрузчиком классов ($TOMCAT_HOME/lib/*. Jar), когда Tomcat инициализирует ресурс TransactionManager для всего контейнера, определенный в
context.xml
осуществляетсяcom.atomikos.icatch.jta.UserTransactionManager
, (Tomcat в настоящее время не использует загрузчик классов веб -приложений.)вы используете
javax.transaction.TransactionManager
класс в вашем веб-приложении, теперь он будет загружен с загрузчиком классов webapp из копии файла JAR, расположенного вwebapp.war/WEB-INF/lib/
папка внутри файла WAR.
Попробуйте удалить файлы JAR, содержащие javax.transaction.TransactionManager
класс из webapp.war/WEB-INF/lib/
и попытайтесь повторно развернуть ваше приложение.
Кроме того, перечислите эти файлы JAR в CLASSPATH
системная переменная, таким образом, эти классы будут загружены системным загрузчиком классов, который имеет приоритет в Tomcat.