Tuesday, September 29, 2009

Mule POC Part II

In my last post I had almost everything working for my first POC interface that transformed a fixed width file to an XML message. What I was missing was putting that XML on an IBM MQ queue.

This I thought would be a snap! But I had a little trouble until I finally got it to work. My solo attempt to finish off this part of the POC was met with the usual cast of characters: "class not found" errors, version issues and general noob mistakes.

IBM MQ JMS Support

After consulting my fearless Sales Solutions Architect, Puneet, he was able to untangle my MQ and JMS configuration. I am still a little fuzzy on how the JMS endpoint is aware of the MQ connection factory when there is no explicit linkage between the two. In any event, here is the bits that allow writing my XML message to an IBM MQ queue:

<spring:bean id="jmsWmqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<spring:property name="hostName" value="localhost"/>
<spring:property name="port" value="1414"/>
<spring:property name="queueManager" value="DEVQMGR"/>
<spring:property name="transportType" value="1"/>
<spring:property name="channel" value="SYSTEM.DEF.SVRCONN"/>
</spring:bean>

<jms:websphere-connector name="JmsConnector" connectionFactory-ref="jmsWmqConnectionFactory"
disableTemporaryReplyToDestinations="true"/>

The jmsWmqConnectionFactory establishes the JMS connection factory. Later I would like to use a JNDI configuration and lookup to get these property values. The obvious reason is to allow environment specific configurations that can be model and replaced at build time. For now though I am just hard coding the connection properties to my local development queue manager. I am using IBM MQ v6.0.2.6.

The next piece in the JMS configuration is the JmsConnector. The JmsConnector references the previously defined connection factory jmsWmqConnectionFactory. And now, the final bit of magic, the JMS outbound endpoint:

<jms:outbound-endpoint queue="QR.12.WMS.IN.PROD_DIM_DL" synchronous="true"/>

I placed this outbound endpoint after my previously defined inbound endpoint and transformers.

Running my now complete cubiscan POC Mule configuration, the following output is generated in the console:

* Server started: 9/30/09 11:31 AM *
* Server ID: 6eb443e8-adef-11de-88f5-41bec82dcb83 *
* JDK: 1.6.0_14 (mixed mode, sharing) *
* OS encoding: Cp1252, Mule encoding: UTF-8 *
* OS: Windows XP - Service Pack 3 (5.1, x86) *
* Host: DEVBXA1-D620 (10.8.25.176) *
* *
* Agents Running: None *
**********************************************************************
[09-30 11:31:31] INFO FileMessageReceiver [fileConnector.receiver.1]: Lock obtained on file: D:\workspace\CubiscanPOC\data\in\Fr152335.csb
[09-30 11:31:31] INFO JmsMessageDispatcher [fileConnector.receiver.1]: Connected: endpoint.outbound.jms://QR.12.WMS.IN.PROD_DIM_DL


I can now browse my queue manager and see the XML message on the QR.12.WMS.IN.PROD_DIM_DL queue. Success!!!

Things I Learned

I had to add a couple of jars that were not part of my initial Mule build path:

mule-jms-provider-1.2.jar
mule-transport-jms-2.2.1.jar

I had to download these from the Mulesoft website and add to my java build path in Eclipse.

I also had to add an MQ jar:

IBM_LIB/com.ibm.mqjms.jar

Where IBM_LIB is where your local IBM jars reside. Mine was located at C:/Program Files/IBM/WebSphere MQ/Java/lib

I kind of got lost trying to follow some example in other online posts and books. But with the variety of JMS providers out there and differences between version 1.x and 2.x of Mule, my original JMS configuration was broken. But no worries, it all got sorted as I said with Puneet's help. Thanks Puneet.

Here is the final Mule configuration:



<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesource.org/schema/mule/core/2.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:stdio="http://www.mulesource.org/schema/mule/stdio/2.2"
xmlns:file="http://www.mulesource.org/schema/mule/file/2.2"
xmlns:xm="http://www.mulesource.org/schema/mule/xml/2.2"
xmlns:vm="http://www.mulesource.org/schema/mule/vm/2.2"
xmlns:jms="http://www.mulesource.org/schema/mule/jms/2.2"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.mulesource.org/schema/mule/core/2.2 http://www.mulesource.org/schema/mule/core/2.2/mule.xsd
http://www.mulesource.org/schema/mule/stdio/2.2 http://www.mulesource.org/schema/mule/stdio/2.2/mule-stdio.xsd
http://www.mulesource.org/schema/mule/file/2.2 http://www.mulesource.org/schema/mule/file/2.2/mule-file.xsd
http://www.mulesource.org/schema/mule/vm/2.2 http://www.mulesource.org/schema/mule/vm/2.2/mule-vm.xsd
http://www.mulesource.org/schema/mule/xml/2.2 http://www.mulesource.org/schema/mule/xml/2.2/mule-xml.xsd
http://www.mulesource.org/schema/mule/jms/2.2 http://www.mulesource.org/schema/mule/jms/2.2/mule-jms.xsd">
<description> </description>

<file:connector name="fileConnector" autoDelete="false" streaming="false"
moveToDirectory="data/archive" fileAge="10000" pollingFrequency="5000"
moveToPattern="#[ORIGINALNAME]_#[SYSTIME]"/>

<custom-transformer name="FixedWidthToMapsTransformer"
class="com.mulesource.mule.transport.jdbc.transformers.FixedWidthToMapsTransformer">
<spring:property name="mappingFile" value="map.cubiscan.xml"/>
</custom-transformer>

<custom-transformer name="MapsToXMLTransformer"
class="com.mulesource.mule.transport.jdbc.transformers.MapsToXMLTransformer"> </custom-transformer>

<xm:xslt-transformer name="Xslt" xsl-file="xsl/cubiscanMap2WMS.xslt"/>

<spring:bean id="jmsWmqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<spring:property name="hostName" value="localhost"/>
<spring:property name="port" value="1414"/>
<spring:property name="queueManager" value="DEVQMGR"/>
<spring:property name="transportType" value="1"/>
<spring:property name="channel" value="SYSTEM.DEF.SVRCONN"/>
</spring:bean>

<jms:websphere-connector name="JmsConnector" connectionFactory-ref="jmsWmqConnectionFactory"
disableTemporaryReplyToDestinations="true"/>

<!--spring:bean id="myConnector" class="org.mule.providers.jms.JmsConnector">
<spring:property name="jndiInitialFactory"
value="com.sun.jndi.fscontext.RefFSContextFactory"/>
<spring:property name="jndiProviderUrl" value="file:///C:/JNDI-Directory"/>
<spring:property name="specification" value="1.1"/>
<spring:property name="connectionFactoryJndiName"
value="com.ibm.mq.jms.MQQueueConnectionFactory"/>
</spring:bean-->


<!--endpoint name="JMSEndPoint" address="jms://productDim" synchronous="false"
connector-ref="myConnector"/-->

<model name="cubiscanPOC">
<!--
A Mule service defines all the necessary information about how your
components will interact with the framework, other components in the
system and external sources. Please refer to the Configuration Guide
for a full description of all the parameters.
-->
<service name="Cubiscan2XML">
<inbound>
<file:inbound-endpoint path="data/in"
transformer-refs="FixedWidthToMapsTransformer MapsToXMLTransformer Xslt"
synchronous="true"/>
</inbound>

<outbound>
<!-- pass-through-router>
<stdio:outbound-endpoint system="OUT" />
</pass-through-router -->
<pass-through-router>
<jms:outbound-endpoint queue="QR.12.WMS.IN.PROD_DIM_DL" synchronous="true"/>
</pass-through-router>
</outbound>
</service>


</model>

</mule>




Next I want to add simple JNDI lookup and move on to my next POC interface. My next POC interface will read from a database and generate a CSV file email attachment.

1 comment:

  1. Puneet showed me how to add maven dependencies so my eclipse project dependencies won't get whipped out. I add these dependencies to my pom file:

    <dependency>
    <groupId>com.ibm.mq</groupId>
    <artifactId>com.ibm.mqjms</artifactId>
    <version>6.0</version>
    </dependency>

    <dependency>
    <groupId>com.ibm.mq</groupId>
    <artifactId>dhbcore</artifactId>
    <version>6.0</version>
    </dependency>

    <dependency>
    <groupId>com.ibm.mq</groupId>
    <artifactId>com.ibm.mq</artifactId>
    <version>6.0</version>
    </dependency>

    After re-running mvn at the project workspace directory, the dependencies were identified and I added the external jars to the maven repository:

    mvn install:install-file -DgroupId=com.ibm.mq -DartifactId=com.ibm.mqjms -Dversion=6.0 -Dpackaging=jar -Dfile="C:\Program Files\IBM\WebSphere MQ\Java\lib\com.ibm.mqjms.jar"
    mvn install:install-file -DgroupId=com.ibm.mq -DartifactId=dhbcore -Dversion=6.0 -Dpackaging=jar -Dfile="C:\Program Files\IBM\WebSphere MQ\Java\lib\dhbcore.jar"
    mvn install:install-file -DgroupId=com.ibm.mq -DartifactId=com.ibm.mq -Dversion=6.0 -Dpackaging=jar -Dfile="C:\Program Files\IBM\WebSphere MQ\Java\lib\com.ibm.mq.jar"

    ReplyDelete