Converting WebSphere ESB resources for use in IBM Integration Bus: Part 2

This two-part article series shows you how to convert WebSphere Enterprise Service Bus (WebSphere ESB) resources so that they can be used by the new IBM Integration Bus product. Part 2 uses the WebSphere ESB StockQuote sample to show you how to convert a variety of mediation primitives. It also describes the conversion tool's extension points and the manual actions you may need to do after running the conversion tool.

Ben Thompson (bthomps@uk.ibm.com), Consulting IT Specialist, IBM

Photo of Ben ThompsonBen Thompson is the Lead Architect for Industry Integration Packs on the IBM Integration Bus Development team at the IBM Software Lab in Hursley Park, United Kingdom. He joined IBM in 2000 and has worked with WebSphere Message Broker since Version 2. For many years, he worked as a consultant with IBM Software Services for WebSphere, designing and implementing WebSphere solutions for IBM customers worldwide. You can contact Ben at bthomps@uk.ibm.com.



14 August 2013

Introduction

This article shows you how to convert the resources in the WebSphere ESB StockQuote sample (which is included with IBM Integration Designer) into IBM Integration Bus resources. The StockQuote sample uses an export with a SOAP/JMS web service binding. Input JMS messages are logged by the StockQuote mediation flow, which then uses a customer ID value from the input, and based on a lookup in a file, determines whether the customer has a subscription level of Regular or Premium. The input message itself is transformed using an XML map into a different message format, which can be sent using an import with a SOAP/HTTP web service binding to one of two back-end services. Messages from Premium customers are routed to the RealtimeService, while messages from Regular customers are routed to the DelayedService. Whichever service is invoked, the response message returned from the callout is transformed into a response message, which StockQuote then returns back to the JMS client. The relationships between the WebSphere ESB components are shown in the Assembly Diagram below:

Assembly diagram for WebSphere ESB StockQuote sample
Assembly diagram for WebSphere ESB StockQuote sample

A project interchange file named PI_WESB_StockQuote.zip is provided in the Download section at the bottom of the article. It contains two unconverted projects, as shown below in Table 1:

Description of the WebSphere ESB resources for conversion in PI_WESB_StockQuote.zip
IID ProjectProject TypePurpose
ResourcesLibraryThis library contains business object definitions that model the messages that are exchanged with the StockQuote and StockQuoteProvider mediation flows.
StockQuoteMediation ModuleThis mediation module contains the exports, imports, and mediation flow component that will be converted into IBM Integration Bus resources.

Part 1 of this article series discussed how to run the IBM Integration Bus conversion tool, so the steps will not be covered in detail here. Launch the IBM Integration Bus Integration Toolkit and start from an empty workspace. Import the downloadable WebSphere ESB Project Interchange file PI_WESB_StockQuote.zip and launch the conversion tool. Create a named conversion session in the default project location WESB_Conversions.

Next, follow the five steps of the conversion tool in order to generate IBM Integration Bus resources. If you choose the default settings as you progress through the conversion process, then the tool will generate a message flow and associated resources, leaving several manual to-do tasks after the tool has run. The rest of this article describes these to-do tasks in detail. This discussion will show some of the conceptual differences in approach between WebSphere ESB and IBM Integration Bus, and should help when you are converting your own WebSphere ESB resources. Fifteen to-do tasks are listed on the review page in the last step of the conversion tool, and this may seem like a lot to do at first glance, several of these tasks can be tackled together.

Conversion tool to-do tasks

Message Logger primitive

The first primitive in the Request part of the StockQuote mediation flow is a Message Logger primitive named Log. Message Logger mediation primitives are used to record messages in a relational database as they pass through a mediation flow. IBM Integration Bus supplies several nodes that can insert data into a relational database. The Compute and Database nodes do this using ODBC communication with the database, while the JavaCompute and Mapping nodes do this using JDBC communication with the database.

One of the to-do tasks explains that by default, the conversion tool converts Message Logger primitives are found in WebSphere ESB mediation flows into IBM Integration Bus placeholder subflows. It is then up to the user to replace the Passthrough node inside this subflow with the particular IBM Integration Bus message flow node (or nodes) which they would like to use. Those familiar with the Message Logger primitive usually prefer to continue using JDBC, which narrows the IBM Integration Bus choice down to either writing code in a JavaCompute node, or doing the task graphically using a map. This article demonstrates a graphical solution, as shown in Figure 2:

Log subflow representing replacement nodes for WebSphere ESB Message Logger primitive
Log subflow representing replacement nodes for WebSphere ESB Message Logger primitive xxx

The main job of inserting the data is done by the Mapping node. IBM Integration Bus maps model the input data which they expect to receive. In order to make this solution applicable regardless of the format of the incoming data, the map is designed to receive the data in the BLOB message domain. The map casts the BLOB data into text which can be inserted into a column of the database defined as a CLOB (Character Large OBject). Defining the column as a CLOB data type makes it easily readable when selecting from the database using either the DB2 Command Line Processor or using the DB2 Control Center. The purpose of the Reset Content Descriptor node, named RCD, which precedes the map, is to change the inbound message into the BLOB message domain. This makes the solution reusable regardless of the message domain which arrives on the input to the Log subflow. For example, it could be a JMS message, DFDL message, or XMLNSC message. The purpose of the Flow Order node which precedes the RCD node is to ensure that the branch of the subflow which does the insert into the database is attempted before the original input message is sent to the out terminal of the subflow. This design also ensures that the original message, in its original message domain, can be sent to the output of the subflow. If an exception were to occur with the database insert, the TryCatch node would catch the problem and route the exception to the Failure terminal of the subflow.

A user can manually add this subflow once the conversion tool has run, but the conversion tool also provides an extension mechanism which allows a desired node or set of nodes to be automatically created as part of the conversion process to replace all examples wherever a mediation primitive of a particular type occurs. This is configured on the third step of the convert tool, as shown below in Figure 3:

Adding a custom converter class for a Mediation primitive
Figure 03

The following instructions demonstrate how to configure an extension Mediation Primitive Converter, using the example of replacing the MessageLogger with the subflow solution discussed above. The converter class which creates the subflow solution is provided with this article in MessageLoggerConverterClass.java inside the Java project WESB_ConversionExtensions. This project is provided inside the attached project interchange file which is named PI_ConversionExtension.zip. Import this project interchange file into your workspace before continuing.

  1. By default, the MessageLogger primitive is converted to a Subflow placeholder by the Converter class named Placeholder converter. Click on Placeholder converter in the Converter class column, as shown in Figure 3 above, to launch the Select Converter Class dialog.
  2. Next to the Converter Java class field, click on the Select button.
  3. In the resulting Open Type dialog select the MessageLoggerConverterClass and then click the OK button.
  4. You will be returned to the previous dialog with the Converter Java class field now populated. Click the OK button.
  5. You will be returned to the original Conversion Tool except now the Converter class column entry for the MessageLogger primitive will have been set to use the provided extension.

Go through the remaining steps of the conversion tool, just like before. On the fourth step, when you click the Start Conversion button you will be warned that the projects which were created when you first ran the tool will be over-written. This is fine, so just click OK on the dialog.

After you have re-run the tool, you should find that the To-Do task list no longer has an entry warning you about the MessageLogger primitive, and the number of remaining To-Do tasks should be 14.

Fail primitive

Two of the tasks in the To-Do list, explain how the conversion tool does not have a built-in capability to convert the instances of the Fail primitive which have been located in the WebSphere ESB mediation flow. By default the conversion tool will replace examples of this mediation primitive with a subflow containing an IBM Integration Bus Passthrough message flow node. The closest equivalent node in IBM Integration Bus is the Throw node. A Throw node is used to generate (throw) an exception on the current branch of the flow. The exception will then be caught and processed by the nearest preceding TryCatch node, or the nearest preceding node which has a Catch terminal, such as a SOAPInput node for example. IBM Integration Bus will insert the exception information into the system log. Replace the two placeholder subflows which were generated in place of the original Fail primitives with Throw nodes. Having done this, return to the To-Do task list and mark the two tasks relating to the Fail primitives as complete. The number of remaining To-Do task list entries is now 12.

XSL Transformation primitive lookup map

The StockQuote mediation flow contains an XSL Transformation primitive named Lookup. This primitive uses a map to assign a value into the SMO context using a Lookup transform. The Lookup transform takes a CustomerId value from the inbound message, and uses it as a key to perform a lookup inside a predefined file which contains Comma Separated Values. The file contains a specification for whether the customerID in question is classified as having a subscription level of premium or regular. Premium customers are privileged and therefore allowed to call a quicker real-time service. Regular customers must make do with a slower call to a delayed service. An example of the CSV file which the Lookup transform accesses is shown below in Listing 1:

Content of the lookup file CustomerType.csv
CustomerA,premium
CustomerB,premium
CustomerC,premium
CustomerD,regular
CustomerE,premium
CustomerF,regular
CustomerG,premium
CustomerH,regular

Unfortunately maps which are used by the IBM Integration Bus Mapping node, do not have a direct equivalent to the WebSphere ESB Lookup transform. For this reason, the Lookup transform is replaced by the Conversion tool by a Task in the generated IBM Integration Bus map, as shown below in Figure 4:

Extract from IBM Integration Bus map Lookup_req_1 showing a Task substituted for the WebSphere ESB Lookup Transform
Figure 04

IBM Integration Bus maps could use a SELECT from a database table to achieve this kind of functional requirement. Using a database in an IBM Integration Bus map is documented in the IBM Integration Bus information center, but here we will consider another alternative within IBM Integration Bus which continues to use a file for the lookup. A FileRead node can be used for this purpose. You can use the FileRead node to read one record, or the entire contents of a file, from within the middle of a message flow allowing you to route or enrich messages going through a flow based on a lookup in the file. Delete the Mapping node named Lookup which the conversion tool generated, and drag and drop a FileRead node as a replacement into the position that it occupied in the StockQuote_MediationFlow_getQuote_request.subflow. Join the FileRead node to the rest of the subflow:

  • Wire the Output terminal of the Log subflow to the In terminal of the FileRead node
  • Wire the Out terminal of the FileRead node to the In terminal of the Filter node
  • Wire the No match terminal of the FileRead node to the In terminal of the Filter node

Configure the properties of the FileRead node's Basic tab. Set the Input directory to be C:\Resources and set the File name or pattern property to be CustomerType.csv. Next, switch to the Result tab of the FileRead node's properties. The properties on this tab address how the required data from the CSV file should be extracted. IBM Integration Bus will parse the CSV file using a DFDL message model. A library named CSVModel is provided for this purpose inside the attached project interchange file which is named PI_CSVModel.zip. Import this project interchange file into your workspace before continuing. Right click the IIB_StockQuote project and choose Manage Library References and then add a reference to the CSVModel library.

Structure of schema changes

The structure of the described schema changes has been chosen not only for the purpose of the FileRead node, but also for the sake of the JAXB Java Compute node (discussed below). It is strongly recommended that you adopt the style of schema described here. Otherwise, when you use it later to generate JAXB classes, you may get different and unwanted results.

The FileRead node will also use an XML schema to describe the fields in the LocalEnvironment tree which will be used to carry information about the subscription level which a sender of a particular request message is entitled to. Before configuring the FileRead node, we need to slightly alter this schema (which was one of the converted resources originating from WebSphere ESB). The changes will add a global element definition to the Subscription schema which is located in the IIB_Resources project, in the namespace package http://Resourse. Open SubscriptionInformation.xsd and make the following two small alterations. Having made the changes described, the resulting schema is shown below in Listing 2:

  • Add a namespace prefix declaration for the targetNamespace.
  • Add a global element named SubscriptionInformation and make the complexType (originally also named SubscriptionInformation) an anonymous definition inside the new global element
Listing for SubscriptionInformation.xsd after making the required changes
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema targetNamespace="http://Resourse"
            xmlns:sub="http://Resourse"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="SubscriptionInformation">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" name="subscriptionLevel" type="xsd:string">
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Save the schema, and then return to the Result properties tab of the FileRead node. The Result data location property specifies which field should be taken from the CSV file. The XPath expression which is used for this field navigates to the required place in the logical tree structure into which the file's CSV data is parsed. The Output data location property specifies where the value taken from the CSV file should be placed in the logical message tree structure which is passed out of the File Read node. To edit these two properties, click Edit and then use the XPath Expression builder as shown in Figure 5:

Using the XPath Expression Builder to set the Result data location
Figure 05

The purpose of the XPath Expression builder dialog is to inform IBM Integration Bus how to model the variable parts of the logical tree. This is done by clicking the Add Data Type link and then selecting the relevant XML schema element. The final values of the two fields should be:

  • Result data location: $ResultRoot/DFDL/CustomerType/record/field2
  • Output data location: $OutputLocalEnvironment/Variables/sub:SubscriptionInformation/subscriptionLevel

The LocalEnvironment tree which we have been editing is a scratch-pad area of the logical message tree which is passed in memory between the nodes of an IBM Integration Bus message flow. It is very similar in concept to the correlation part of the SMO tree used by WebSphere ESB.

The final property which is set on the Result tab of the FileRead node is named the Record selection expression. The expression defined here tells the FileRead node how to decide which record from the CSV file should be used. This is based upon using the value of the customerID field as a key to perform the lookup:

Record selection expression:
$InputRoot/XMLNSC/tns:getQuote/request/customerID = $ResultRoot/DFDL/CustomerType/record/field1

The Input Message Parsing tab specifies how the FileRead node should attempt to parse data from the file. As discussed, use the DFDL parser for this task. Set the properties:

Message domain: DFDL
Message: {}:CustomerType

IBM Integration Bus provides a wizard to help you generate DFDL message models which can be used to parse many different kinds of non-XML data such as fixed length messages, tagged delimited formats, and of course many complex industry standard formats. The DFDL model is provided with this article but if you're interested in how this was created then you can read more about this in the IBM Integration Bus Information Center. Having configured the FileRead node, return to the To-Do task list and mark the task concerning the Lookup primitive as completed: Having done this, the number of remaining To-Do task list entries is 11.

Message Filter primitive

The conversion tool replaces instances of the Message Filter primitive with Route nodes in the resulting IBM Integration Bus message flows. Locate the Route node (named Filter) and examine its Basic properties. The Filter patterns refer to the context section of the WebSphere ESB (SMO) tree. You will need to change the Filter pattern for both the entries in the table to refer to the subscriptionLevel element in the Local Environment section of the IBM Integration Bus logical tree. Select each row in turn in the Filter table, and click the Edit button and set the values as shown in below, and then save the subflow:

Properties of the Route node named Filter
Filter patternRouting output terminal
$LocalEnvironment/Variables/sub:SubscriptionInformation/subscriptionLevel='premium'realtime
$LocalEnvironment/Variables/sub:SubscriptionInformation/subscriptionLevel='default'delayedTime

Message Element Setter primitive

The conversion tool replaces Message Element Setter primitive instances with Java Compute nodes in the resulting IBM Integration Bus message flows. There are two alternative API formats which can be used in conjunction with Java Compute nodes in IBM Integration Bus. The IBM Integration Bus Java Integration API provides methods to navigate around the logical tree which passes through the message flow. This approach has been available since Java Compute nodes were first introduced to the product many years ago. The second approach is to convert the IBM Integration Bus logical tree into an XML DOM tree and then use JAXB get and set methods (generated from an XML schema) to change the tree's structure and values. The Java Compute nodes which are generated by the conversion tool are configured to use the JAXB approach. This design decision has been deliberately taken so that a user can apply the (possibly many) setter instructions which were configured on the original Message Element Setter primitive in any order. Because the node has knowledge of the output data format, the setter instructions will be applied and the output message will have its fields generated in the corrected order. If the other form of Java Compute node had been utilized then the fields would be generated in the order of execution of the statements.

The conversion tool creates a Java Compute node for the SetCustomerType primitive, but it is the responsibility of the developer to use the XML schemas to generate the JAXB get and set methods and then to manually add code to the node's Java template to carry out the set statements which are copied across as comments. The following instructions describe how to do this:

  1. From the Start menu, open an IBM Integration Console 9.0.0.0 and change directory to the bin folder of the Java Development Kit which is included with the IBM Integration Bus Toolkit installation. If you have used the default installation location this will be at C:\Program Files (x86)\IBM\IntegrationToolkit90\jdk\bin
  2. The XML schema StockQuoteRequest.xsd models the data coming into and leaving the SetCustomerType node. The purpose of the node is to set a default subscriptionLevel in the LocalEnvironment tree but leave the message itself unchanged. To achieve this we need only generate the Java object classes from the schema which described the subscription level:
    xjc.exe -d <workspace_location>\IIB_StockQuoteJava -p jaxb_classes 
        <workspace_location>\IIB_Resources\SubscriptionInformation.xsd
  3. Return to IBM Integration Toolkit, switch to the Java perspective and refresh the IIB_StockQuoteJava project and you should now see the jaxb_classes package which you just generated.
  4. From within the IIB_StockQuoteJava project, open StockQuote_MediationFlow_getQuote_request_SetCustomerType.java which you will find in the default package. Look through the code template and you should find that the conversion tool has helpfully added a comment describing the set statements which are required:
    // SET /context/correlation/subscriptionLevel to "regular"

    Replace the content of the entire file with the following code from Listing 3:
Java code for StockQuote_MediationFlow_getQuote_request_SetCustomerType.java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import org.w3c.dom.Document;
import com.ibm.broker.javacompute.MbJavaComputeNode;
import com.ibm.broker.plugin.MbException;
import com.ibm.broker.plugin.MbMessage;
import com.ibm.broker.plugin.MbMessageAssembly;
import com.ibm.broker.plugin.MbOutputTerminal;
import com.ibm.broker.plugin.MbUserException;
import com.ibm.broker.plugin.MbXMLNSC;
import jaxb_classes.SubscriptionInformation;

public class StockQuote_MediationFlow_getQuote_request_SetCustomerType 
    extends MbJavaComputeNode {

    protected static JAXBContext jaxbContext = null;

    public void onInitialize() throws MbException {
            try {
            // Initialize the JAXB context with the Java object
            // classes that were generated by a JAXB binding compiler
            jaxbContext = JAXBContext.newInstance("jaxb_classes");
        } catch (JAXBException e) {
            // This exception will cause the deploy of this Java compute node to fail
            // Typical cause is the JAXB package above is not available
            throw new MbUserException(this, "onInitialize()", "", "",e.toString(), null);
        }
    }

    public void evaluate(MbMessageAssembly assembly) throws MbException {
        MbOutputTerminal out = getOutputTerminal("out");
        MbMessage localEnvironment = assembly.getLocalEnvironment();

        try {
            // ----------------------------------------------------------
            // Add user code below to build the new output data by updating 
            // your Java objects or building new Java objects
            SubscriptionInformation outputLocalEnvironmentJavaObject
                = new SubscriptionInformation();
            outputLocalEnvironmentJavaObject.setSubscriptionLevel("regular");
            // End of user Java object processing
            // ----------------------------------------------------------

            // Marshal the new or updated output Java object class into the Broker tree
            Document outDocumentLocalEnvironment
                = localEnvironment.createDOMDocument(MbXMLNSC.PARSER_NAME);
            jaxbContext.createMarshaller().marshal(outputLocalEnvironmentJavaObject,
                outDocumentLocalEnvironment);
            localEnvironment.getRootElement().getFirstElementByPath
                (MbXMLNSC.PARSER_NAME).setName("Variables");
            // Propagate the output message assembly
            out.propagate(assembly);
        } catch (JAXBException e) {
            throw new MbUserException(this, "evaluate()", "", "", e.toString(), null);
        }
    }
}

Having configured this node, return to the To-Do task list and mark the two tasks concerning the SetCustomerType primitive as completed. Having done this, the number of remaining To-Do task list entries is 9.

XSL Transformation primitive TransformToRealtime map

The purpose of the TransformToRealtime map in the original WebSphere ESB mediation flow is to transform the StockQuote Request message into the request format for the Realtime service. The conversion tool will have automatically converted the WebSphere ESB XML map to an IBM Integration Bus map. The automatic conversion has been successful, however the conversion tool still provides a warning To-Do task to check for any errors or warnings but in this example there aren't any, so you can return to the To-Do list stored in the conversion session file and mark the task as complete. Having done this, the number of remaining To-Do task list entries is 8.

XSL Transformation primitive TransformToDelayed map

The transformation between the StockQuote request message and the request format for the Delayed service has a very similar To-Do task entry as the one we have just dealt with. Again, a quick comparison of the maps shows that the automated conversion tool has perfectly converted the mapping and that there are no validation or warning messages. Return to the To-Do list stored in the conversion session file and mark the task as complete. Having done this, the number of remaining To-Do task list entries is 7.

Callout primitive RealtimeService import

The conversion tool automatically replaces instances of the WebSphere ESB Callout mediation primitive with a SOAPRequest node in the generated IBM Integration Bus message flows. In the generated subflow named StockQuote_MediationFlow_getQuote_Request.subflow, find the SOAPRequest node named RealtimeService and you will see that its Basic properties have been automatically configured. The conversion tool warns you that the end point address which can be found on the HTTP Transport property tab of the SOAPRequest node has been assigned a value based on the original Callout primitive. This warning is a reminder that if the service being called was also implemented in WebSphere ESB, then it is likely that you will want to change this URL. This article provides example stubs to simulate both the Realtime and Delayed services - implemented as IBM Integration Bus Services. These stub services are provided so that you can successfully test the converted message flows at runtime, without the need to install a WAS or WebSphere ESB environment. Change the port number in the Web service URL property to be 7800. The new Web Service URL should be:

http://localhost:7800/StockQuoteProviderWeb/sca/RealtimeServicePortTypeExport1

Return to the To-Do list stored in the conversion session file and mark the warning about the end point as complete. Having done this, the number of remaining To-Do task list entries is 6.

Callout primitive DelayedService import

We will now repeat the same task for the SOAPRequest node which communicates with the Delayed Service. In the generated subflow named StockQuote_MediationFlow_getQuote_Request.subflow, find the SOAPRequest node named DelayedService, and on the HTTP Transport properties tab, change the Web service URL. so that the port number is 7800. The new web service URL should be:

http://localhost:7800/StockQuoteProviderWeb/sca/DelayedServicePortTypeExport1

Return to the To-Do list stored in the conversion session file and mark the warning about the end point as complete. Having done this, the number of remaining To-Do task list entries is 5.

XSL Transformation primitive RealtimeToStockQuoteService map

Having made a request to either the Realtime Service or the Delayed Service, the flow uses further maps to transform the Realtime response message into the StockQuote response message, and the Delayed response message into the Stockquote response message. These maps are converted automatically, but we will now edit them in order to map the subscriptionLevel from the Local Environment tree into the qualityOfService element, which is found in the StockQuote Response message. Doing this in the maps will mean we can completely remove the SetQualityOfService primitive (which comes after the map nodes) from the IBM Integration Bus message flow altogether.

From within the IIB_StockQuote project, open RealtimeToStockQuoteService_res_1.map and click the source Message Assembly so that its properties appear at the base of the screen. On the properties tab click the link Headers and folders: Properties and in the pop-up window, add the LocalEnvironment tree to the map source by ticking the LocalEnvironment box and clicking OK. Expand the LocalEnvironment tree which has now been added to the map source, and right-click the any element under the Variables subtree of the LocalEnvironment. Choose the Cast menu action as shown below in Figure 6:

Adding a defined structure to the Variables section of the LocalEnvironment
Figure 06

From the resulting Type Selection dialog, choose the SubscriptionInformation element and click OK. Having added the SubscriptionInformation element to the LocalEnvironment, expand the tree and then drag and drop the subscriptionLevel element to the qualityOfService element in the getQuoteResponse target message. Click on the Move transform which you just created and look at its properties. Set the array index (highlighted with the red box in Figure 7 below) to be the value 1. This step removes a warning from the Problems view of the Toolkit which reminds you that a cardinality should be set when mapping from an array.

Setting the input array index on the RealtimeToStockQuoteService Map
Figure 07

Save the map and return to the To-Do list stored in the conversion session file and mark the warning about the map as complete. Having done this, the number of remaining To-Do task list entries is 4.

XSL Transformation primitive DelayedToStockQuoteService map

Now make the same alterations to the DelayedToStockQuoteService map which you will find located in the IIB_Resources project. Edit the automatically converted map to move the subscriptionLevel from the LocalEnvironment tree into the qualityOfService element in the StockQuote Response message. Just like the last map change that we performed, be sure to set the array index on the Move transform to be the value 1. This step removes a warning from the Problems view of the Toolkit which reminds you that a cardinality should be set when mapping from an array. Save the map and return to the To-Do list stored in the conversion session file and mark the warning about the map as complete. Having done this, the number of remaining To-Do task list entries is 3.

Message Element Setter primitive SetQualityOfService

The Message Element Setter primitive named SetQualityOfService is converted into a JavaCompute node. However, due to the earlier changes which were made to the maps DelayedToStockQuoteService and RealtimeToStockQuoteService, when the message arrives at this point in the flow, the assignment of the QualityOfService field in the preparation of the StockQuote response message has already been done. For this reason, there is no longer any need to keep this node in the message flow, so it should be deleted. Wire the two mapping nodes directly to the output node (StockQuoteService_getQuote_InputResponse). Also delete the file containing the java class which the node referenced. You will find this file named StockQuote_MediationFlow_getQuote_request_SetQualityOfService.java which is inside the project IIB_StockQuoteJava. Return to the conversion session's To-do task list and mark the two tasks relating to the SetQualityOfService node as complete. Having done this, there should be only one further To-Do task list entry requiring action.

StockQuote export JMS binding

When the conversion tool generates the IIB_StockQuote.msgflow, the SOAPInput node is configured in place of the Web Services (JMS) Export binding on the WebSphere ESB StockQuote service. This node will receive the initial request which causes the StockQuote service to get invoked. The node is set up to receive messages over the JMS transport (on the node's Basic properties tab, Transport = JMS). Examine the JMS Transport properties tab and you will see that by default the tool suggests that WebSphere MQ be used as the JMS provider. However, the Source, JNDI URL bindings location and Connection factory name all require configuration. A conversion To-Do task list entry was added to remind users that this should be done manually after conversion. We will do this now. Set the values on the SOAPInput node as listed below in Table 3. These JMS settings correctly correspond to the JMS resources which we will set up before testing the flow.

JMS Properties of the SOAPInput node in IIB_StockQuote.msgflow
Property NameProperty Value
SourceStockQuoteService
JNDI URL bindings locationfile:/C:/JNDI-Directory
Connection factory nameStockQuoteServiceQCF

Once configured the JMS properties should look like Figure 8:

JMS Properties of the SOAPInput node in IIB_StockQuote.msgflow
Figure 08

Save the message flow and return to the conversion session's To-do task list and mark the last task relating to the JMS Transport properties as complete. Save the conversion session file. Having made all of the changes discussed, StockQuote_MediationFlow_getQuote_request.subflow should look like Figure 9:

Final StockQuote_MediationFlow_getQuote_request.subflow
Figure 09

Configure JMS bindings and queue definitions

Before testing the converted resources, the following instructions will help you set up a JMS input queue and output queue. This article includes an attached file named Resources.zip. Extract the file's contents to the directory C:\Resources (you can choose another directory but this location is assumed by later instructions in the article). This file contains the following files:

Contents of attached file Resources.zip file
File NamePurpose
StockQuoteJMS.defA configuration file for creating the required JMS definitions.
StockQuoteWMQ.mqscA configuration file for creating the required WMQ queues.
CustomerType.csvThe lookup file which the scenario uses to determine whether to call the Realtime or Delayed service.
JMSUtil.jarA test utility which is provided for putting and getting JMS messages.

Now check whether you have an existing JNDI bindings file. On Windows platforms, by default the bindings file will be located in the directory C:\JNDI-Directory. If this directory contains a .bindings file then the definitions which are created using the instructions below will be added to this file. Alternatively, you can delete your existing bindings file and the instructions below will create a new bindings file from scratch. You can also configure WMQ to use an entirely new bindings file in a different location. If you wish to do this, then navigate to the WMQ installation subdirectory <WMQ_Installation_Directory>\java\bin. Add the following changes shown in Listing 4 to the JMSAdmin.config file. The PROVIDER_URL property points to the directory where you would like to generate the bindings:

Additions to JMSAdmin.config
INITIAL_CONTEXT_FACTORY=com.sun.jndi.fscontext.RefFSContextFactory
PROVIDER_URL=file:/C:/JNDI-Directory

Having configured the location for the bindings file, the following instructions describe how to generate the JMS definitions:

  1. Open an IBM Integration Bus Command Console window and change directory to the WMQ installation directory which is being used by the runtime broker that you intend to use for testing, and move to its subdirectory <WMQ_Installation_Directory>\java\bin. If you installed WMQ to the default location, then this will be C:\Program Files (x86)\IBM\WebSphere MQ\java\bin.
  2. Use the JMSAdmin command to set up the required Queue Connection Factory and queues:
    JMSAdmin.bat < C:\Resources\StockQuoteJMS.def

    The StockQuoteJMS.def file is provided with this article. It contains the following instructions (it is assumed that you will be using the default IBM Integration Bus configuration which involves a broker named IB9NODE, associated with a queue manager named IB9QMGR, which uses a listener on port 2414):

    DEF QCF(jms/StockQuoteServiceQCF) TRANSPORT(CLIENT) CHANNEL(SYSTEM.BKR.CONFIG)+ 
        HOST(127.0.0.1) PORT(2414) QMGR(IB9QMGR) 
    DEFINE Q(jms/StockQuoteService) QUEUE(STOCKQUOTE.IN) QMGR(IB9QMGR) 
    DEFINE Q(jms/StockQuoteServiceResponse) QUEUE(STOCKQUOTE.OUT) QMGR(IB9QMGR)
    END
  3. Next, use the runmqsc command to set up the required WMQ queues (to which the JMS definitions above will bind). Do this from the same IBM Integration Bus Command Console window:
    runmqsc IB9QMGR < C:\Resources\StockQuoteWMQ.mqsc

    The StockQuoteWMQ.mqsc file is provided with this article. It contains the following instructions:
    def ql(STOCKQUOTE.IN)
    def ql(STOCKQUOTE.OUT)

Create the Log database

Earlier in the article we discussed the conversion extension point which replaces the WebSphere ESB Message Logger primitive with a Mapping node to insert data into a DB2 database. In order for this part of the flow to work, we need to create the database ready to receive the data to be logged:

  1. From the Windows start menu, launch the DB2 Command Line Processor window. Create the database using the following command:
    create db LOGDB
  2. In the same DB2 Command Line Processor window, connect to the database which you just created:
    connect to LOGDB
  3. Now create a table to store the data:
    CREATE TABLE DATAWAREHOUSE (MESSAGEDATA CLOB (1 M) NOT NULL,
    DBINSERTTIMESTAMP TIMESTAMP NOT NULL WITH DEFAULT CURRENT_TIMESTAMP)
  4. Exit the DB2 Command Line Processor:
    disconnect all
    quit
    exit

Create IBM Integration Bus JDBC configurable service

The runtime IBM Integration Bus Node where you intend to deploy your flow will need to be configured to be able to connect via JDBC to the Log database. You can create the configurable service by launching an IBM Integration Bus command console and then using the following command:

mqsicreateconfigurableservice IB9NODE -c JDBCProviders -o LOGDB 
    -n databaseName,databaseType,databaseVersion,jarsURL,portNumber,
        serverName,type4DatasourceClassName,type4DriverClassName 
    -v LOGDB,DB2,9.7,"C:\Program Files\IBM\SQLLIB\java",50000,
        localhost,com.ibm.db2.jcc.DB2XADataSource,com.ibm.db2.jcc.DB2Driver

If the user id under which you run the IBM Integration Bus node does not have authority to access the database, you will also need to run the mqsisetdbparms command to authorize the flow to insert data into the database.

Deploy converted resources

  1. IBM Integration Bus resources (Integration Services) are provided to simulate the Realtime and Delayed services with which the StockQuoteService communicates. Import RealtimeService and DelayedService from the project interchange file named PI_IIB_StubServices.zip which is provided with this article.
  2. Create a Broker Archive file inside a project in your Integration Toolkit workspace (such as inside IIB_StockQuote for example), and on the Prepare tab, select the application IIB_StockQuote, and the two Integration Services DelayedService and RealtimeService:
    Broker Archive File
    Figure 10
  3. Click the Build and Save button and then deploy the BAR file to your default configuration:
    Deployed resources
    Figure 11

Test converted resources

A test tool (called JMSUtil) is provided with this article which can be used to write a JMS message of the correct format to the input queue, and retrieve the response message which IBM Integration Bus will write to the reply queue.

  1. Open an IBM Integration Bus Command Console and (assuming you followed the instructions earlier in the article) change directory to C:\Resources.
  2. The JMSUtil application needs access to the JMS libraries provided with WebSphere MQ, so assuming you installed WMQ to the default location, launch the application with the command shown below:
    java -jar JMSUtil.jar -cp "C:\Program Files (x86)\IBM\WebSphere MQ\java\lib"
  3. JMSUtil is launched with the correct settings pre-configured for the JMS bindings discussed earlier in the article, so the Connection tab properties will already have been set for you, as shown below:
    JMSUtil Connection Properties
    Figure 12
    Switch to the Header tab properties and you will see that the JMSReplyTo queue has also been defined for you to match with the definition we created earlier.
    JMSUtil Header Properties
    Figure 13
    Switch to the Data tab properties and you will see that the data carried in the body of the message has also been defined. If you wish to change the message when doing your own testing, you can edit the text directly using your keyboard:
    JMSUtil Data
    Figure 14
    Switch back to the Connection tab properties and click the Write Message button. The Status and Current Queue Depth properties will be updated to show the message has been written to the queue successfully:
    JMSUtil Data Written to the queue successfully
    Figure 15
  4. Assuming the IBM Integration Bus flow has executed successfully all the way through, we will now read the response message from the queue. Change the JMS Destination Name to be StockQuoteServiceResponse and click the Read Message button. The Status should show a successful read has occurred, and the Current Queue Depth should now read as zero (the message has just been taken from the response queue):
    JMSUtil message read from the response queue successfully
    Figure 16
  5. Switch to the Data properties tab and you should see that it contains the response message which came from the IIB_StockQuote service:
    JMSUtil data view of the response message
    Figure 17

Check Log database

The Log subflow which was used as the replacement for the Message Logger primitive should have copied the input message which was propagated through the IBM Integration Bus flow into the DATAWAREHOUSE table of the LOGDB database which we created earlier. Open a DB2 Control Center and check the contents of the table. You should see something like . The input message to the StockQuote service has been logged with a timestamp.

Message logged to the DB2 database
Figure 18

Conclusion

IBM Integration Bus V9 is IBM's new strategic integration product (built upon the same architecture as WebSphere Message Broker). The Integration Bus Toolkit provides the first capability for converting build-time resources which were originally created to support WebSphere Enterprise Service Bus use cases. This article has demonstrated using the tool to convert a simple mediation and also discussed some of the architectural differences between the two products. The second article in this series involves a more complex scenario based on the WebSphere Enterprise Service Bus StockQuote sample which shows a wider range of mediation primitives being converted and also discusses the conversion tool's extension points.


Downloads

DescriptionNameSize
Code samplePI_ConversionExtension.zip5 KB
Code samplePI_CSVModel.zip3 KB
Code samplePI_IIB_StubServices.zip31 KB
Code samplePI_WESB_StockQuote.zip38 KB
Code sampleResources.zip12 KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=941424
ArticleTitle=Converting WebSphere ESB resources for use in IBM Integration Bus: Part 2
publish-date=08142013