JBoss AS7 HornetQ (XA, Spring, Hibernate)
renevanwijk Aug 20, 2012 4:33 AMIn an application build with Spring (and Hibernate for the ORM) we have the following Spring configuration:
{code:xml}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<bean id="company" class="model.logic.CompanyBean">
<property name="sessionFactory" ref="sessionfactory"/>
<property name="jmsTemplate" ref="jmstemplate"/>
</bean>
<!-- Hibernate SessionFactory config -->
<bean id="sessionfactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="jtaTransactionManager" ref="transactionManager"/>
<property name="mappingResources">
<list>
<value>model/entities/person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop>
<prop key="hibernate.listeners.envers.autoRegister">${hibernate.listeners.envers.autoRegister}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
</props>
</property>
</bean>
<!-- Transaction config -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Resource look-ups -->
<jee:jndi-lookup id="datasource" jndi-name="java:/jdbc/OracleDS" resource-ref="false"/>
<jee:jndi-lookup id="connectionfactory" jndi-name="java:/JmsXA" resource-ref="false"/>
<jee:jndi-lookup id="destination" jndi-name="java:/queue/test" resource-ref="false"/>
<!-- JMS config -->
<bean id="jmstemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionfactory"/>
<property name="defaultDestination" ref="destination"/>
</bean>
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionfactory"/>
<property name="destination" ref="destination"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="messageListener" ref="companymdp"/>
</bean>
<bean id="companymdp" class="model.logic.CompanyMDP"/>
<!-- Extra -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:spring.properties</value>
</list>
</property>
</bean>
</beans>
{code}
The used resources (that are looked-up) are configured on JBoss as follows:
{code:xml}
<domain xmlns="urn:jboss:domain:1.1">
...
<profiles>
<profile name="cluster">
<subsystem xmlns="urn:jboss:domain:datasources:1.0">
<datasources>
<datasource jta="true" jndi-name="java:/jdbc/OracleDS" pool-name="OracleDS" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:oracle:thin:@192.168.1.60:1521:orcl11</connection-url>
<driver>oracle</driver>
<pool>
<min-pool-size>1</min-pool-size>
<max-pool-size>15</max-pool-size>
<prefill>true</prefill>
<use-strict-min>true</use-strict-min>
</pool>
<security>
<user-name>example</user-name>
<password>example</password>
</security>
<timeout>
<idle-timeout-minutes>0</idle-timeout-minutes>
<query-timeout>600</query-timeout>
</timeout>
<statement>
<prepared-statement-cache-size>10</prepared-statement-cache-size>
</statement>
</datasource>
<drivers>
<driver name="oracle" module="com.oracle.database">
<driver-class>oracle.jdbc.OracleDriver</driver-class>
<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
<subsystem xmlns="urn:jboss:domain:messaging:1.1">
<hornetq-server>
...
<jms-connection-factories>
...
<pooled-connection-factory name="hornetq-ra">
<transaction mode="xa"/>
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/JmsXA"/>
</entries>
</pooled-connection-factory>
</jms-connection-factories>
<jms-destinations>
<jms-queue name="testQueue">
<entry name="java:/queue/test"/>
<entry name="java:jboss/exported/jms/queue/test"/>
</jms-queue>
...
</jms-destinations>
</hornetq-server>
</subsystem>
...
</profile>
</profiles>
...
<deployments>
<deployment name="LoadTest6.ear" runtime-name="LoadTest6.ear">
<content sha1="161f51dde7f085c822cc4c68b306d57f1bee902d"/>
</deployment>
<deployment name="SpringHibernate.war" runtime-name="SpringHibernate.war">
<content sha1="574d0617d92d8439844633557937be754a134370"/>
</deployment>
</deployments>
<server-groups>
...
<server-group name="cluster-group" profile="cluster">
<jvm name="default"/>
<socket-binding-group ref="cluster-sockets"/>
<deployments>
<deployment name="LoadTest6.ear" runtime-name="LoadTest6.ear"/>
<deployment name="SpringHibernate.war" runtime-name="SpringHibernate.war" enabled="false"/>
</deployments>
</server-group>
</server-groups>
</domain>
{code}
In the jboss-deployment-structure looks as follows:
{code:xml}
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.springframework">
<imports>
<include path="META-INF**"/>
<include path="org**"/>
</imports>
</module>
</dependencies>
</deployment>
</jboss-deployment-structure>
{code}
in which the org.springframework module has the following contents:
{code:xml}
<module xmlns="urn:jboss:module:1.1" name="org.springframework">
<resources>
<resource-root path="aopalliance-1.0.jar"/>
<resource-root path="cglib-2.2.2.jar"/>
<resource-root path="commons-logging-1.0.4.jar"/>
<resource-root path="org.springframework.aop-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.asm-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.beans-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.context-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.core-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.expression-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.jdbc-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.jms-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.orm-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.transaction-3.1.2.RELEASE.jar"/>
<resource-root path="org.springframework.web-3.1.2.RELEASE.jar"/>
</resources>
<dependencies>
<module name="javax.api" export="true"/>
<module name="org.apache.log4j" export="true"/>
<module name="org.antlr" export="true"/>
<module name="org.dom4j" export="true"/>
<module name="org.hibernate" export="true"/>
<module name="javax.persistence.api" export="true"/>
<module name="org.javassist" export="true"/>
<module name="org.jboss.logging" export="true"/>
<module name="javax.transaction.api" export="true"/>
<module name="javax.jms.api" export="true"/>
</dependencies>
</module>
{code}
When the application is run, the following is observed:
{code}
# LOGGING CLUSTER SERVER 1
09:33:20,815 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@74359b24: startup date [Fri Aug 17 09:33:20 CEST 2012]; root of context hierarchy
09:33:20,945 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) Loading XML bean definitions from class path resource [spring-config.xml]
09:33:21,415 INFO [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) Loading properties file from class path resource [spring.properties]
09:33:21,441 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6c11e58: defining beans [company,sessionfactory,datasource,propertyConfigurer,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,connectionfactory,destination,jmstemplate,org.springframework.jms.listener.DefaultMessageListenerContainer#0,companymdp]; root of factory hierarchy
09:33:21,535 INFO [org.springframework.transaction.jta.JtaTransactionManager] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) Using JTA UserTransaction: org.jboss.tm.usertx.client.ServerVMClientUserTransaction@7e0cf590
09:33:21,536 INFO [org.springframework.transaction.jta.JtaTransactionManager] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) Using JTA TransactionManager: com.arjuna.ats.jbossatx.jta.TransactionManagerDelegate@4d50b06b
09:33:21,537 INFO [org.springframework.transaction.jta.JtaTransactionManager] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) Using JTA TransactionSynchronizationRegistry: com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionSynchronizationRegistryImple@38d060ac
09:33:21,784 INFO [org.hibernate.annotations.common.Version] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) HCANN000001: Hibernate Commons Annotations {4.0.1.Final}
09:33:21,792 INFO [org.hibernate.Version] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) HHH000412: Hibernate Core {4.0.1.Final}
09:33:21,794 INFO [org.hibernate.cfg.Environment] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) HHH000206: hibernate.properties not found
09:33:21,796 INFO [org.hibernate.cfg.Environment] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) HHH000021: Bytecode provider name : javassist
09:33:21,907 WARN [org.hibernate.internal.util.xml.DTDEntityResolver] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) HHH000223: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/. Use namespace http://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
09:33:22,517 INFO [org.hibernate.dialect.Dialect] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect
09:33:22,539 INFO [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) HHH000397: Using ASTQueryTranslatorFactory
09:33:22,652 INFO [org.hibernate.validator.util.Version] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) Hibernate Validator 4.2.0.Final
09:33:23,152 INFO [org.springframework.context.support.DefaultLifecycleProcessor] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) Starting beans in phase 2147483647
09:33:23,552 INFO [stdout] (ajp-axis-into-ict.nl-192.168.1.150-9080-7) INSERT 1chrw6b78f2w9 9719
09:33:23,671 WARN [org.springframework.jms.listener.DefaultMessageListenerContainer] (org.springframework.jms.listener.DefaultMessageListenerContainer#0-1) Execution of JMS message listener failed, and no ErrorHandler has been set.: java.lang.RuntimeException: javax.jms.IllegalStateException: Non XA connection
at model.logic.CompanyMDP.onMessage(CompanyMDP.java:16) [classes:]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:562) [org.springframework.jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:500) [org.springframework.jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:468) [org.springframework.jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:326) [org.springframework.jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:244) [org.springframework.jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1071) [org.springframework.jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1063) [org.springframework.jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:960) [org.springframework.jms-3.1.2.RELEASE.jar:3.1.2.RELEASE]
at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_31]
Caused by: javax.jms.IllegalStateException: Non XA connection
at org.hornetq.ra.HornetQRASession.getSession(HornetQRASession.java:1246)
at org.hornetq.ra.HornetQRAMessage.acknowledge(HornetQRAMessage.java:71)
at model.logic.CompanyMDP.onMessage(CompanyMDP.java:13) [classes:]
... 9 more
{code}
It is complaining about the connection not being XA (Non XA connection) - looking in the HornetQ documentation (http://docs.jboss.org/hornetq/2.2.14.Final/user-manual/en/html_single/index.html) it is shown that an XA-typed connection factory can be obtained when using the 'xa' element. But when this is used in the JBoss configuration (and the host controller and servers are restarted) the following error is observed in the host controller logging:
{code}
Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[697,29] Message: JBAS014789: Unexpected element '{urn:jboss:domain:messaging:1.1}xa' encountered
{code}
Looks like the 'urn:hornetq' is different than the 'urn:jboss:domain:messaging:1.1', so things that are shown in the HornetQ documentation cannot always be used in the JBoss messaging configuration.
At first, I thought there was something wrong with the application, and set-up a similar environment in WebLogic. Here, it is working fine.
I am missing something in the JBoss configuration (such as libraries, wrong config...)? More detailed information can be found here: http://middlewaremagic.com/weblogic/?p=8104.
Note the application described above is simplified version of the real application (only involving the necessary resources - JMS, database and transactions)