We are using Apache Camel to perform most of our ETLs. We are also using NodeRed for small things. For WebSphere MQ, I don’t think that it is possible to connect to the MQ using the IBM native protocol via NodeRed. So we will do this with Camel.
Creating the factory
We will be using a xml spring route definition file.
We need to first create a connection factory by adding a bean to the spring xml file. That’s the easy part.
<bean id="wmq" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory"> <bean class="com.ibm.mq.jms.MQQueueConnectionFactory"> <property name="transportType" value="1" /> <property name="channel" value="CHANNEL" /> <property name="hostName" value="X.X.X.X" /> <property name="port" value="3414" /> <property name="queueManager" value="QUEUEMANAGER" /> </bean> </property> </bean>
Once that done, you can easily link your favorite broker like Rabbit MQ or Active MQ to WebSphereMQ using a route like the one shown below:
<route> <from uri="jms:queue:FROM.MY.BROKER"/> <to uri="wmq:TO.QUEUE.WMQ"/> <log message="Success !!!!!!!!!!!!!!!!!!!!!!!!!!"/> </route>
In order for this to work, you must of course have com.ibm.mq.jms.MQQueueConnectionFactory class available in your classpath. Nowadays this is easier than ever because the IBM WMQ client can be added as a maven dependency like shown below in your pom.xml:
<dependency> <groupId>com.ibm.mq</groupId> <artifactId>com.ibm.mq.allclient</artifactId> <version>18.104.22.168</version> </dependency>
If the WebSphere MQ is secured, there is a great chance that you will not be able to connect and get a few dozen lines of errors that are not that useful.
- First issue that you can have is that you must specify which protocol to use in the client. This can be done by adding the property sSLCipherSuite to the factory.
<bean id="wmq" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory"> <bean class="com.ibm.mq.jms.MQQueueConnectionFactory"> <property name="transportType" value="1" /> <property name="channel" value="CHANNEL" /> <property name="hostName" value="X.X.X.X" /> <property name="port" value="3414" /> <property name="queueManager" value="QUEUEMANAGER" /> <property name="sSLCipherSuite" value="TLS_RSA_WITH_AES_256_GCM_SHA384" /> </bean> </property> </bean>
- Second issue could be linked to certificates
Most of the times, there will be two certificates that must be added: a client and a server one.
I was not able to add them the “Spring” way, so most of the time, I simply import them using the keytool java application in the JVM.
keytool -import -trustcacerts -keystore /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts -storepass changeit -noprompt -alias cert1 -file /camelbin/conf/cert1.arm
Do this for all the certificates by changing the alias and using the appropriate file path. Restart your camel application and everything should work fine.
Note that it is also possible to change the target client mode by setting the following header:
<setHeader headerName="CamelJmsDestinationName"> <constant>queue:///YOUR.QUEUE.NAME?targetClient=1</constant> </setHeader>
If it still does not work, it is possible to force a p12 truststore and keystore via the java command line.
java -Dtrust_all_cert=true -Djavax.net.ssl.keyStore=/camelbin/conf/mycrts.p12 -Djavax.net.ssl.keyStorePassword=***** -Dtrust_all_cert=true -Djavax.net.ssl.trustStore=/camelbin/conf/mycrts.p12 -Djavax.net.ssl.trustStorePassword=***** -Dcom.ibm.mq.cfg.useIBMCipherMappings=false -Djava.library.path=file:./lib -Dlog4j.configuration=file:./conf/log4j.xml -DWorkflowName=$WORKFLOW_NAME -DServerID=$SERVERID -jar CamelRunner.jar start file:./conf/config.xml autorestart docker
Note that the the path to the truststore depends on the JVM. In the previous example, we are using OpenJDK in a docker container.
In order to create a p12 store, you can use the KeyStore Explorer app.
The p12 must contain the two following certs:
- The public certificate from the MQ server
- The private certificate generated from the MQ Server for the client