Monday, July 28, 2014

How to configure local JMS transactions using Camel with WebSphere MQ on JBoss EAP 6.2

In this article I will show you how to configure local JMS transactions using WebSphere MQ with Camel on JBoss EAP 6.2:

Your Spring context setup should include the following information:
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="java:jboss/eis/MQCF" />
            <property name="lookupOnStartup" value="false" />
            <property name="cache" value="true" />
            <property name="proxyInterface" value="javax.jms.ConnectionFactory" />
 </bean>

 <bean id="jmsTransactionManager"           class="org.springframework.transaction.jta.JtaTransactionManager">
            <property name="transactionManagerName" value="java:/TransactionManager" />
  </bean>

  <bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
            <property name="connectionFactory" ref="jmsConnectionFactory" />
            <property name="transacted" value="true" />
            <property name="transactionManager" ref="jmsTransactionManager" />
   </bean>
The important stuff here is to use JtaTransactionManager.

In the JBoss EAP 6.2 configuration the WebSphere resource-adapter should be configured like this:

<subsystem xmlns="urn:jboss:domain:resource-adapters:1.1">
     <resource-adapters>
             <resource-adapter id="wmq.jmsra.rar">
                   <archive>
                        wmq.jmsra.rar
                    </archive>
                    <transaction-support>LocalTransaction</transaction-support>
                    <connection-definitions>
                        <connection-definition class-name="com.ibm.mq.connector.outbound.ManagedConnectionFactoryImpl" jndi-name="java:jboss/eis/MQCF" enabled="true" use-java-context="true" pool-name="WMQConnectionFactoryPool" use-ccm="true">
                            <config-property name="port">
                                MQ.PORT
                            </config-property>
                            <config-property name="channel">
                                MQ.CHANNEL
                            </config-property>
                            <config-property name="hostName">
                                MQ.HOST
                            </config-property>
                            <config-property name="transportType">
                                CLIENT
                            </config-property>
                            <config-property name="queueManager">
                                MQ.QUEUEMANAGER
                            </config-property>
                            <pool>
                                <min-pool-size>1</min-pool-size>
                                <max-pool-size>10</max-pool-size>
                            </pool>
                        </connection-definition>
                  </connection-definitions>
            </resource-adapter>
      </resource-adapters>
</subsystem>

In case you want to use the JBoss CLI to set things up you can use the following script:

if (outcome != success) of /subsystem=resource-adapters/resource-adapter=wmq.jmsra.rar:read-resource() /subsystem=resource-adapters/resource-adapter=wmq.jmsra.rar:add(archive=wmq.jmsra.rar,transaction-support=XATransaction) /subsystem=resource-adapters/resource-adapter=wmq.jmsra.rar/connection-definitions=WMQConnectionFactoryPool:add(class-name=com.ibm.mq.connector.outbound.ManagedConnectionFactoryImpl, jndi-name="java:jboss/eis/MQCF", enabled=true, use-java-context=true, use-ccm=true,min-pool-size=1, max-pool-size=10) /subsystem=resource-adapters/resource-adapter=wmq.jmsra.rar/connection-definitions=WMQConnectionFactoryPool/config-properties=connectionNameList:add(value="${wmq.connectionNameList}") /subsystem=resource-adapters/resource-adapter=wmq.jmsra.rar/connection-definitions=WMQConnectionFactoryPool/config-properties=channel:add(value="${wmq.channel}") /subsystem=resource-adapters/resource-adapter=wmq.jmsra.rar/connection-definitions=WMQConnectionFactoryPool/config-properties=transportType:add(value="CLIENT") /subsystem=resource-adapters/resource-adapter=wmq.jmsra.rar/connection-definitions=WMQConnectionFactoryPool/config-properties=queueManager:add(value="${wmq.queueManager}") end-if

In this script I'm using system-variables that you could define in a property file and pass it on during JBoss EAP via the -P parameter.

Finally to get everything working you should replace the MQ.* values with you actual settings and copy wmq.jmsra.rar to JBOSS_HOME/standalone/deployments.

In case you are using an EAR to package your application and you don't want include WebSphere MQ libraries, you can add a jboss-deployment-structure.xml inside the META-INF directory of the EAR with the following content:

<jboss-deployment-structure>
    <deployment>
        <dependencies>
            <module name="deployment.wmq.jmsra.rar" export="true" />
        </dependencies>
    </deployment>
</jboss-deployment-structure>

To declare a dependency of your EAR to wmq.jmsra.rar also in order of deployment add jboss-all.xml to the same META-INF directory:

<jboss umlns="urn:jboss:1.0">
    <jboss-deployment-dependencies xmlns="urn:jboss:deployment-dependencies:1.0">
        <dependency name="wmq.jmsra.rar" />
    </jboss-deployment-dependencies>
</jboss>