Search This Blog

Friday, December 18, 2015

Automated testing using JUnit, Maven and Jenkins.

Preface

In my earlier post we went about the task of using Apache Tomcat as the application server that had Jenkins running in it as the Continuous Integration and Continuous Deployment application and Git as the source code repository. It also did the approval and checked for inline tasks that were completed and approved before deployment. One piece of missing cog in this is the automated testing application that we cans use to do Test Driven Development. Lets take a stab at that in this post.

Maven for Eclipse

For this I used Maven as the Project management application ans JUnit as the testing application tool. Maven can be installed as an Eclipse plugin. To do so click on the 'Help' and then 'Install New Software' button as shown below.  


I am using the IBM Integration Bus toolkit at version 10 and found that the closest Maven plugin would be http://download.eclipse.org/technology/m2e/releases/1.4 . Add this to the list.


Select the first plugin from the list as shown below.


After the software has been installed in eclipse just to be safe restart eclipse. 

Creating a Maven project in Eclipse

To create a maven project for testing.


Select the Maven Project option.


Create a simple project


Give it a Group Id and a Artifact Id and click on the button finish.


All done the project structure should look like this. The pom.xml contains the dependencies for the project. The test cases will be create in the src->test->java folder and the surefire reports will be created in the target folder.

 


Java API to run the JUnit test cases

Before we move any forward lets take a pause and understand what we have done till now. We installed the Maven plugin in our IIB toolkit and created a Maven project. To run the test cases, we need a java API that will write messages to queue, read messages from queue, send messages to http and also put a request message on a request queue and expect a response on the reply queue. I have added the Util class that has these methods and it can be downloaded from the this location. Import the project in eclipse and create a jar file as com.testing.mq.jar. We will be using this as one of the external libraries.

Jar files for Maven projects

Note:-This procedure is generally not recommended. It is better to have an external Maven repository that maintains the jar files. Some types of the free/open source repositories are JFrog's artifactory or apache's archiva. This page details the steps that will help you to import the jar files in a maven repository. 

Coming back to our project, create a folder called 'libs' in the project and import the following libraries into this folder- 

JUnit jar file can be downloaded from this location.
XMLUnit jar file can be downloaded from this location.

The other jar files needed in this case are available in the {WebSphereMQ Install Location}\java\lib folder.

Update the pom.xml file with the dependencies by adding the dependency block as following - 

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<systemPath>${basedir}/libs/junit-4.12.jar</systemPath>
<scope>system</scope>

</dependency>

Test cases and test data

We have all the libraries ready, create 3 folders in the project and name them as 'InputFile', 'ExpectedFile' and 'OutputFile'. As the name specifies each of them will contain the input file for the test, the expected output of the operation and the actual OutputFile. 


In this instance there are 2 test cases, one is for the request containing just one stock quote request and the other is with multiple stock quote request.

The Next step would be to create the test case file in the folder src->test by right clicking the test folder and then selecting 'New' and 'Other'. Select the 'JUnit Test Case'

Following is a sample of the test case details. Please note the name is a general requirement to have it suffixed with 'Test'.


Here is the JUnit class file -


package com.AggregateStockQuote;



import java.io.IOException;
import org.custommonkey.xmlunit.*;
import org.junit.Test;
import org.xml.sax.SAXException;
import com.testing.mq.Util;

public class StockSingleReqTest extends XMLTestCase {

@Test
public void test() throws IOException, InterruptedException, SAXException {
// fail("Not yet implemented");
String inputFile = System.getProperty("user.dir")
+ "/InputFile/StockQuoteReqSingle.xml";
String outputFile = System.getProperty("user.dir")
+ "/OutputFile/StockQuoteRepSingle.xml";
String controlFile = System.getProperty("user.dir")
+ "/ExpectedFile/StockQuoteRepSingle.xml";

Util newUtil = new Util();
newUtil.queueRequestReply("WQM.INT", 
"AGG.REQ", 
"AGG.REP", 
inputFile, 
outputFile,
8);

String controlXML = newUtil.readFile(controlFile);
String testXML = newUtil.readFile(outputFile);

DifferenceListener myDifferenceListener = new IgnoreTextAndAttributeValuesDifferenceListener();
Diff myDiff = new Diff(controlXML, testXML);
myDiff.overrideDifferenceListener(myDifferenceListener);
assertTrue("test XML matches control skeleton XML " + myDiff,
myDiff.similar());
// assertTrue("Comparing test xml to control xml", controlXML, testXML);

}
}

As the request and response is XML we are using xmlunit to ascertain if the request and response is similar. The different options available and an example of how to use it is available at this location.

Create a similar test for the Multi request and the folder should look like this.

Running the JUnit test case

Now that we have the artifacts done the next step is to run the test cases. To run the test cases, right click on the project and select the 'Maven test' as follows -  



If the test run successfully the console will be populated with the verbose details - in this case we had the following output - 

Results :

Failed tests:   test(com.AggregateStockQuote.StockMultiReqTest): test XML matches control skeleton XML org.custommonkey.xmlunit.Diff
  test(com.AggregateStockQuote.StockSingleReqTest): test XML matches control skeleton XML org.custommonkey.xmlunit.Diff

Tests run: 2, Failures: 2, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19.431s
[INFO] Finished at: Fri Dec 18 10:27:42 EST 2015
[INFO] Final Memory: 6M/10M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.10:test (default-test) on project JUnit_AggregationStockQuote: There are test failures.

The following artifacts are created in the target folder. The test-classes folder contain the complied class files of the junit test. The surefire-reports contains the results of the test that were run and they are in XML and TXT format. 

The text reports contain the output of the test cases. If they have been success or failure - 

SUCCESS

-------------------------------------------------------------------------------

Test set: com.AggregateStockQuote.StockSingleReqTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.957 sec 

FAILURE

-------------------------------------------------------------------------------
Test set: com.AggregateStockQuote.StockSingleReqTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.957 sec <<< FAILURE!
test(com.AggregateStockQuote.StockSingleReqTest)  Time elapsed: 7.955 sec  <<< FAILURE!
junit.framework.AssertionFailedError: test XML matches control skeleton XML org.custommonkey.xmlunit.Diff
[different] Expected number of child nodes '16' but was '1' - comparing <Stock...> at /StockQuotes[1]/Stock[1] to <Stock...> at /StockQuotes[1]/Stock[1]

at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.Assert.assertTrue(Assert.java:22)
at junit.framework.TestCase.assertTrue(TestCase.java:192)
at com.AggregateStockQuote.StockSingleReqTest.test(StockSingleReqTest.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56)
at java.lang.reflect.Method.invoke(Method.java:620)
at junit.framework.TestCase.runTest(TestCase.java:176)
at junit.framework.TestCase.runBare(TestCase.java:141)
at junit.framework.TestResult$1.protect(TestResult.java:122)
at junit.framework.TestResult.runProtected(TestResult.java:142)
at junit.framework.TestResult.run(TestResult.java:125)
at junit.framework.TestCase.run(TestCase.java:129)
at junit.framework.TestSuite.runTest(TestSuite.java:252)
at junit.framework.TestSuite.run(TestSuite.java:247)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56)
at java.lang.reflect.Method.invoke(Method.java:620)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)


XML Surefire reports

Double click on one of the surefire report's xml and 

One can also run the test case from the JUnit perspective as shown above by right clicking on the test and selecting 'Run'


Running JUnit from Jenkins

Now that we have accomplished the task of executing the Maven project in eclipse we can externalize the project by having it run from Jenkins. Create a project in Jenkins with the following details - 
Save it and it is now available to run. Check on the console output after the project has finished running and it would appear something like this - 

SuccessConsole Output

Started by user intuser
Building in workspace C:\JenkinsHome\workspace\JUnit_MFA_AggregationStockQuote_MVN
Parsing POMs
Established TCP socket on 63238
[JUnit_AggregationStockQuote] $ C:\Java\jdk1.8.0_60/bin/java -cp C:\JenkinsHome\plugins\maven-plugin\WEB-INF\lib\maven32-agent-1.7.jar;D:\Build\apache-maven-3.3.3\boot\plexus-classworlds-2.5.2.jar;D:\Build\apache-maven-3.3.3/conf/logging jenkins.maven3.agent.Maven32Main D:\Build\apache-maven-3.3.3 D:\Build\apache-tomcat-8.0.22\webapps\jenkins\WEB-INF\lib\remoting-2.52.jar C:\JenkinsHome\plugins\maven-plugin\WEB-INF\lib\maven32-interceptor-1.7.jar C:\JenkinsHome\plugins\maven-plugin\WEB-INF\lib\maven3-interceptor-commons-1.7.jar 63238
<===[JENKINS REMOTING CAPACITY]===>channel started
Executing Maven:  -B -f C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\pom.xml install
[INFO] Scanning for projects...
[WARNING] 
[WARNING] Some problems were encountered while building the effective model for JUnit_AggregationStockQuote:JUnit_AggregationStockQuote:jar:0.0.1-SNAPSHOT
[WARNING] 'dependencies.dependency.systemPath' for junit:junit:jar should not point at files within the project directory, ${basedir}/libs/junit-4.12.jar will be unresolvable by dependent projects @ line 22, column 16
[WARNING] 'dependencies.dependency.systemPath' for xmlunit:xmlunit:jar should not point at files within the project directory, ${basedir}/libs/xmlunit-1.4.jar will be unresolvable by dependent projects @ line 29, column 16
[WARNING] 'dependencies.dependency.systemPath' for com.ibm:com.ibm.mqjms:jar should not point at files within the project directory, ${basedir}/libs/com.ibm.mqjms.jar will be unresolvable by dependent projects @ line 39, column 16
[WARNING] 'dependencies.dependency.systemPath' for com.ibm:com.ibm.mq.headers:jar should not point at files within the project directory, ${basedir}/libs/com.ibm.mq.headers.jar will be unresolvable by dependent projects @ line 47, column 16
[WARNING] 'dependencies.dependency.systemPath' for com.ibm:connector:jar should not point at files within the project directory, ${basedir}/libs/connector.jar will be unresolvable by dependent projects @ line 55, column 16
[WARNING] 'dependencies.dependency.systemPath' for com.ibm:com.ibm.mq.jmqi:jar should not point at files within the project directory, ${basedir}/libs/com.ibm.mq.jmqi.jar will be unresolvable by dependent projects @ line 63, column 16
[WARNING] 'dependencies.dependency.systemPath' for com.ibm:com.ibm.mq.commonservices.jar:jar should not point at files within the project directory, ${basedir}/libs/com.ibm.mq.commonservices.jar will be unresolvable by dependent projects @ line 71, column 16
[WARNING] 'dependencies.dependency.systemPath' for testingmq:testingmq:jar should not point at files within the project directory, ${basedir}/libs/com.testing.mq.jar will be unresolvable by dependent projects @ line 79, column 16
[WARNING] 'dependencies.dependency.systemPath' for mqclasses:mqclasses:jar should not point at files within the project directory, ${basedir}/libs/com.ibm.mq.jar will be unresolvable by dependent projects @ line 86, column 16
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING] 
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building JUnit_AggregationStockQuote 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ JUnit_AggregationStockQuote ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\src\main\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ JUnit_AggregationStockQuote ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ JUnit_AggregationStockQuote ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\src\test\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ JUnit_AggregationStockQuote ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\target\test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ JUnit_AggregationStockQuote ---
[INFO] Surefire report directory: C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.AggregateStockQuote.StockMultiReqTest
MQJE001: Completion Code '2', Reason '2033'.
A WebSphere MQ Error occured : Completion Code 2 Reason Code 2033
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.721 sec
Running com.AggregateStockQuote.StockSingleReqTest
MQJE001: Completion Code '2', Reason '2033'.
A WebSphere MQ Error occured : Completion Code 2 Reason Code 2033
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.988 sec

Results :

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

[JENKINS] Recording test results
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ JUnit_AggregationStockQuote ---
[INFO] Building jar: C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\target\JUnit_AggregationStockQuote-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ JUnit_AggregationStockQuote ---
[INFO] Installing C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\target\JUnit_AggregationStockQuote-0.0.1-SNAPSHOT.jar to C:\Users\Godfrey\.m2\repository\JUnit_AggregationStockQuote\JUnit_AggregationStockQuote\0.0.1-SNAPSHOT\JUnit_AggregationStockQuote-0.0.1-SNAPSHOT.jar
[INFO] Installing C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\pom.xml to C:\Users\Godfrey\.m2\repository\JUnit_AggregationStockQuote\JUnit_AggregationStockQuote\0.0.1-SNAPSHOT\JUnit_AggregationStockQuote-0.0.1-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 31.858 s
[INFO] Finished at: 2015-12-08T10:20:33-05:00
[INFO] Final Memory: 20M/202M
[INFO] ------------------------------------------------------------------------
Waiting for Jenkins to finish collecting data
[JENKINS] Archiving C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\pom.xml to JUnit_AggregationStockQuote/JUnit_AggregationStockQuote/0.0.1-SNAPSHOT/JUnit_AggregationStockQuote-0.0.1-SNAPSHOT.pom
[JENKINS] Archiving C:\Godfrey\git\IIBPoTs\JUnit_AggregationStockQuote\target\JUnit_AggregationStockQuote-0.0.1-SNAPSHOT.jar to JUnit_AggregationStockQuote/JUnit_AggregationStockQuote/0.0.1-SNAPSHOT/JUnit_AggregationStockQuote-0.0.1-SNAPSHOT.jar
channel stopped
Finished: SUCCESS




The JUnit code used for this blog post can be found here.




Friday, December 11, 2015

WMB(IIB), WMQ, ICS and BPM Reference

Broker Help

1.    Some Links from Developerworks to help

a.    What’s new in version 6.1(theory)

http://www.ibm.com/developerworks/websphere/library/techarticles/0802_dunn/0802_dunn.html

b.    Connecting WMB using SSL

http://www.ibm.com/developerworks/websphere/tutorials/0908_muragod/0908_muragod-pdf.pdf

c.    Configure WMB on Linux

http://www.ibm.com/developerworks/websphere/library/techarticles/0804_squibb/0804_squibb.html

d.    Deploying flows to MB using bat script

http://www.ibm.com/developerworks/websphere/library/techarticles/0501_lublinsky/0501_lublinsky.html

e.    Retrying message in MB

http://www.ibm.com/developerworks/websphere/library/techarticles/0601_cox/0601_cox.html

f.     MB Best practices

http://www.ibm.com/developerworks/websphere/library/techarticles/0809_kudikala/0809_kudikala.html

g.    Performance and accounting in MB

http://www.ibm.com/developerworks/websphere/library/techarticles/0710_piatek/0710_piatek.html

h.    Compression and Decompression of messages using MB and Java

http://www.ibm.com/developerworks/websphere/library/techarticles/0711_jain/0711_jain.html

i.     Reduce Memory usage in WMB 6

http://www.ibm.com/developerworks/websphere/library/techarticles/0505_storey/0505_storey.html

j.     Transformation options in WMB 6

http://www.ibm.com/developerworks/websphere/library/techarticles/0608_piper/0608_piper.html

k.    WSRR with WMB

http://www.ibm.com/developerworks/websphere/library/techarticles/0806_crocker/0806_crocker.html

l.     Reconfigure Message Flows

http://www.ibm.com/developerworks/websphere/library/techarticles/0808_lucas/0808_lucas.html

m.  Collector nodes in WMB 6.1

http://www.ibm.com/developerworks/websphere/library/techarticles/0805_coleman/0805_coleman.html

n.    JMS Nodes in WMB v6

http://www.ibm.com/developerworks/websphere/library/techarticles/0604_bicheno/0604_bicheno.html

o.    Business Events in WMB 6.1

http://www.ibm.com/developerworks/websphere/library/techarticles/0810_zhang/0810_zhang.html

p.    SOAP Nodes in WMB 6.1

q.    PUB SUB Requirements-

http://download.boulder.ibm.com/ibmdl/pub/software/dw/wes/pdf/0505_withers-Pubsub_performance_analysis.pdf

r.    PHP Node in 61.

http://www.ibm.com/developerworks/websphere/techjournal/0904_phillips/0904_phillips.html

s.    Automate WMB deployment

http://www.ibm.com/developerworks/websphere/library/techarticles/0706_spriet/0706_spriet.html?ca=drs-

t.     HTTP Nodes overview

http://www.ibm.com/developerworks/websphere/library/techarticles/0608_braithwaite/0608_braithwaite.html

u.    File Handling - version 6.1

http://www.ibm.com/developerworks/websphere/library/techarticles/0806_mcmullan/0806_mcmullan.html

v.    Configure Timer Nodes - version 6.1

http://www.ibm.com/developerworks/websphere/library/techarticles/0603_schutz/0603_schutz.html

w.  Configure SAP adapter – version 6.1

x.    Configuring and administering multi-instance brokers for high availability in IBM WebSphere Message Broker

y.    Introduction to the WebSphere Message Broker global cache

http://www.ibm.com/developerworks/websphere/library/techarticles/1212_hart/1212_hart.html

z.    Using SCA nodes in WebSphere Message Broker V7

http://www.ibm.com/developerworks/websphere/library/techarticles/0912_nagchowdhury/0912_nagchowdhury.html

aa. Integrating with TCP/IP using WebSphere Message Broker

http://www.ibm.com/developerworks/websphere/library/techarticles/1105_ghosh/1105_ghosh.html

bb. What's new in WebSphere Message Broker V7

http://www.ibm.com/developerworks/websphere/library/techarticles/0912_lucas/0912_lucas.html

cc. Using Microsoft .NET in WebSphere Message Broker V8

http://www.ibm.com/developerworks/websphere/tutorials/1112_thompson/index.html
http://www.ibm.com/developerworks/websphere/tutorials/1201_thompson2/index.html
http://www.ibm.com/developerworks/websphere/tutorials/1202_thompson3/index.html
http://www.ibm.com/developerworks/websphere/tutorials/1202_thompson4/index.html

dd. Integrating systems of highly complex message formats with WebSphere Message Broker

http://www.ibm.com/developerworks/websphere/library/techarticles/1208_soultan/1208_soultan.html

ee. Transaction traceability of enterprise files, data, and applications: Part 1: Scenario overview: Integrating IBM Sterling Connect:Direct with WebSphere MQ

http://www.ibm.com/developerworks/websphere/library/techarticles/1206_nadgir1/1206_nadgir1.html
http://www.ibm.com/developerworks/websphere/library/techarticles/1207_nadgir2/1207_nadgir2.html
http://www.ibm.com/developerworks/websphere/library/techarticles/1209_nadgir/1209_nadgir3.html

2.    Automate using ANT scripts

###build.xml###
###########
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0"?>
<project name="project" default="run">
<target name="run" description="">
<property name="toolkit.home" value="C:\Program Files\IBM\IntegrationToolkit90" />
<property name="workspaces.dir" value="C:\Godfrey\Workspaces\IIBT9Workspace" />
<property name="runtime.dir" value="C:\Program Files\IBM\MQSI\9.0.0.2\bin" />
<property name="appln.name" value="MFA_AggregationStockQuote" />
<property name="bar.name" value="${workspaces.dir}\${appln.name}\${appln.name}.bar" />
<property name="Brokername" value="WBRK" />
<property name="execution.group" value="default" />
<antcall target="mqsideploybar" />
</target>

<!--Target to build the broker archive using mqsicreatebar-->
<target name="mqsicreatebar.buildbar">
<echo message="Building Broker Archive file: ${bar.name} " />
<exec executable="${toolkit.home}\mqsicreatebar.exe" spawn="false">
<arg value="-data" />
<arg value="${workspaces.dir}" />
<arg value="-b" />
<arg value="${bar.name}" />
<arg value="-a" />
<arg value="${appln.name}" />
</exec>
<echo message="Completed building Broker Archive file - ${bar.name} " />
</target>

<!--Target to deploy the broker archive using mqsideploybar-->
<target name="mqsideploybar" depends="mqsicreatebar.buildbar">
<echo message="Deploying Broker Archive file: ${bar.name} " />
<exec executable="${runtime.dir}\mqsideployscript.bat" spawn="false">
<arg value="${Brokername}" />
<arg value="-e" />
<arg value="${execution.group}" />
<arg value="-a" />
<arg value="${workspaces.dir}\${appln.name}\${appln.name}.bar" />
</exec>
<echo message="Completed building Broker Archive file - ${bar.name} " />
</target>
</project>


Add the following line to mqsideployscript.bat file at the top so that it can set the MQSI environment.

@call "C:\Program Files\IBM\MQSI\9.0.0.2\bin\mqsiprofile.cmd"

3.    How to set Expiry to a message

To make sure that a message expires after a certain period of time use the following code to set it up in the MQMD header-

SET OutputRoot.MQMD.Expiry = CURRENT_TIMESTAMP + INTERVAL ‘1’ DAYS

If desired the same can be done using direct number as well. For numbers it will be divided by 10 as seconds.

4.    How to use XML transformation node

Use this node to transform any XML message to any format required. For eg. Consider transforming a XML message to a HTML message.Consider the following input message

<Employee>
          <EmpNo>John Doe<EmpNo>
</Employee>

Using the sytlesheet as following
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="Employee">
       <HTML>
         <HEAD>
           <TITLE>Employee document</TITLE>
         </HEAD>
         <BODY>
            <H1>Employee document</H1>
              <H2>Employee Number:<xsl:value-of select="EMPNO"/></H2>
          </BODY>
       </HTML>
   </xsl:template>
</xsl:stylesheet>

The resultant HTML document will be as follows –
       <HTML>
         <HEAD>
           <TITLE>Employee document</TITLE>
         </HEAD>
         <BODY>
            <H1>Employee document</H1>
              <H2>Employee Number:John Doe</H2>
          </BODY>
       </HTML>

5.    How to use Trace node

The trace node is used to direct the trace message to a file if needed or to event viewer if needed. To direct the output to a “File” the following properties should be set-
Destination: File
File Path: The full path of the file to which the trace will be written.
Pattern: the trace pattern-
${Root} for all the root variables data.
${Exception} for all the exception related issues.

          If in case the trace needs to be written to the event viewer select “User Trace”         

6.    Iterate till the last exception is encountered

Sometime it is required by clients to make a note of the exception and enter the same into the database. In such a case the requirement is to iterate till the last exception child and note it.

      -- Create a reference to the first child of the exception list   
      DECLARE ptrException reference to InputExceptionList.*[1];
     
      DECLARE errorNumber CHARACTER;
      DECLARE errorText CHARACTER '';
      DECLARE insertText CHARACTER '';
      DECLARE nodeLabel CHARACTER;
      DECLARE detailErrorText CHARACTER '';
      DECLARE insertCount INTEGER;
      DECLARE count INTEGER 1 ;
-- ** Iterate the while till the pointer of the Exception list has the child.
      WHILE lastmove(ptrExceptionDO
            -- store the current values for the error number and text        
            IF ptrException.Number is not null THEN
                        SET errorNumber = ptrException.Number;
                        SET errorText = errorText || ':' || ptrException.Text;
                        SET nodeLabel = ptrException.Label;
                                        
                  SET detailErrorText=' ErrorCode:' ||errorNumber || ErrorText :' ||errorText||' NodeLabel :'|| nodeLabel ||'; '|| detailErrorText ;
            END IF;
            -- now move to the last child which should be the next exceptionlist         
            move ptrException LASTCHILD;
-- ** Get all the 'Insert' texts
            set insertCount=CARDINALITY(ptrException."Insert"[] );
             while (count <= insertCount ) Do
                  set insertTextinsertText || ':' || ptrException."Insert"[count].Text;
                  set count = count + 1;
                                   
             end while;
           
      END WHILE;

7.    How to use set by corelationid

To use MQGet node for Request/Reply scenario, one would need to store the CoRelation ID to use it to pick the response. In this case have a compute node between MQOutput and MQGet node with the following bit of code.

SET OutputRoot.MQMD.CorrelId = InputLocalEnvironment.WrittenDestination.MQ.DestinationData.msgId;

Change the properties for MQGet to pick the message by correlid.

8.    Propagate the output without deleting it

An alternative method is to instruct the node not to clear the output message on the first two PROPAGATE statements, so that the message is available for routing to the next destination. The code to do this is:

SET OutputRoot = InputRoot;
PROPAGATE DELETE NONE;
SET OutputRoot = InputRoot;
PROPAGATE TO TERMINAL ’Out1’ DELETE NONE;
SET OutputRoot = InputRoot;
PROPAGATE TO LABEL ’ThirdCopy’;

The third option will not have the ‘DELETE NONE ‘ as it needs to clear the output buffer.

9.    Coordinated Transaction using db2swit file

To use coordinated transaction settings using message broker use the following settings-
MQ-Right click the Qmgr, select the properties and XA resource manager tab 
SwitchFile - Select the full patch of the swit file(IIB 10 - C:\IBM\IIB\10.0.0.0\server\sample\xatm\db2swit.dll) 
XAOpenstring is {DATABASE,userid,password}.
Thread control is process.
MessageFlow – Select the coordinated transaction checkbox.

10. ESQL Guideline

While using the parser for incoming message in Compute node -
SET InputBody = InputRoot.XML or InputRoot.MRM

For filter node or Database use –
SET Body = Root.XML

11. How to use RouteToLabel node

This node is used in case the flow of the message needs to be sent to another label based in the same message flow.This is done by using the RouteToLabel node and the Label nodes.
The property for the routetolabel node will be “Route to First”.
The labels will have the properties, as LabelName.This will be the label name to which the message flow is given.
The compute node preceding the RouteToLabel node will have the following data set to route it-

SET OutputLocalEnvironment.Destination.RouterList.DestinationData[1].labelname='SinglePassenger';

12. How to throw an exception or error

      IF (EXISTS(Environement.variables.CornerstonePartyID)=FALSE OR
            EXISTS(Environement.variables.PartyObject)=FALSE OR
            EXISTS(Environement.variables.Session)=FALSETHEN
            THROW USER EXCEPTION VALUES ('Environment variables are not set');
END IF;

13. To THROW an error with access for DataBase errors

If in any case we have some errors related to accessing database and we need to throw  error then it can be done in the following manner.

DECLARE SQLState1 CHARACTER;
DECLARE SQLErrorText1 CHARACTER;
DECLARE SQLCode1 INTEGER;
DECLARE SQLNativeError1 INTEGER;

SET SQLState1 = SQLSTATE;
SET SQLCode1 = SQLCODE;
SET SQLErrorText1 = SQLERRORTEXT;
SET SQLNativeError1 = SQLNATIVEERROR;
--Use the THROW statement to back out the database and issue a user exception—
THROW USER EXCEPTION MESSAGE 2950 VALUES ( ’The SQL State’ , SQLState1 , SQLCode1 , SQLNativeError1 , SQLErrorText1 );

14. Message to DB2 Database

In an effort to write the entire message to a database table use the following piece of code –

DECLARE MSG_BLOB BLOB; 
DECLARE MSG_DATA CHAR; 

SET MSG_BLOB = ASBITSTREAM(InputRoot.XML OPTIONS RootBitStream); 
SET MSG_DATA = CAST( MSG_BLOB AS CHAR CCSID InputRoot.MQMD.CodedCharSetId ENCODING InputRoot.MQMD.Encoding);

 

This will copy the entire message in the MSG_BLOB .

         
Just incase using the PASSTHRU statement –
PASSTHRU('INSERT INTO db2admin.TEST(TESTBLOB) VALUES( ? )', MSG_BLOB);

CREATE LASTCHILD OF OutputRoot.XML PARSE (TESTBLOB OPTIONS RootBitStream);  

15. Use of ITEM keyword

This statement will generate the output as
SET OutputRoot.XML.Test.Result[= (SELECT ITEM T.UnitPrice FROM InputBody.Invoice.Purchases.Item[] AS T);

<Test>
<Result>27.95</Result>
<Result>42.95</Result>
<Result>59.99</Result>
</Test>

If the term ITEM is missed out then the output will be as –

<Test>
<Result>
<UnitPrice>27.95</UnitPrice>
</Result>
<Result>
<UnitPrice>42.95</UnitPrice>
</Result>
<Result>
<UnitPrice>59.99</UnitPrice>
</Result>
</Test>

16. How to work with XMLNSC

DECLARE brw NAMESPACE ’http://www.ibm.com/Borrowed’;
SET OutputRoot.MRM.brw:Borrowed.VideoTitle = ’MRM Greatest Hits’;

17.              To create a tree in Environment for XML message

CREATE FIRSTCHILD OF Environment ‘XML’ ;
SET Environment.XML = Body;

This will create an asis XML message in the Environment tree.The same can then be assigned to another XML tree when required later.

18.              To set null value

SET OutputRoot.MRM.Elem2.Child1 VALUE = NULL;

19. Create reference for Output Message and Input message

In case required to create a reference for creating an output structure this is the way to go about creating it. Unless the field is created the reference cannot be done -

CREATE FIELD OutputRoot.XML.XMLMessage; DECLARE OutputMsg REFERENCE TO OutputRoot.XML.XMLMessage; SET OutputMsg = InputRoot.XML.XMLMessage;

DECLARE MyInputFlight REFERENCE TO InputRoot.ComIbmAggregateReplyBody.FlightDetails.XML.Flight;
DECLARE MyInputPassengers REFERENCE TO InputRoot.ComIbmAggregateReplyBody.PassengerDetails.XML.ListOfPassengers;

20. Publish messages using MQ

The below mentioned piece of code can be used as a reference to publish messages based on topics –

SET OutputRoot.MQMD.MsgType = 1; 
SET OutputRoot.MQMD.ReplyToQ = 'BROKER.REPLY'; 
SET OutputRoot.MQMD.Format = MQFMT_RF_HEADER_2; 
SET OutputRoot.MQRFH2.(MQRFH2.Field)Version = 2; 
SET OutputRoot.MQRFH2.(MQRFH2.Field)Format = 'MQSTR'; 
SET OutputRoot.MQRFH2.(MQRFH2.Field)NameValueCCSID = 1208; 
SET OutputRoot.MQRFH2.psc.Command = 'Publish'; 
SET OutputRoot.MQRFH2.psc.Topic = InputRoot.XMLNS.Publication.TopicName; 
SET OutputRoot.XMLNS.ArchMessage.Data = InputRoot.XMLNS.Publication.Data;

21. To use ContentAssit while writing ESQL

From the toolkit ,select EDIT-> Content Assit.

22. Use of NameSpace

Currently only XMLNSC is allowed with XML having deprecated. So to use the same one has to follow the following convention.
DECLARE soap NAMESPACE ‘http://value/’
SET InputRoot.XMLNSC.soap:ComIbmAggregateReplyBody.FlightDetails.XML.Flight

23. Command to know Execution groups in broker

To know the execution groups that have been deployed in the broker use the following command –
mqsibrowse <BROKER NAME> -t BROKERAAEG

24. Command to know Published and Subscribed topics

To know the topics that have been published as well as subscribed use the following command-
mqsibrowse <BROKER NAME> -t BSUBSCRIPTIONS

25. Run a trace for Broker

To put a broker on a trace –
1.Right click the execution group that you want to set for tracing and then select Debug
2.From the command line issue the command
mqsichangetrace <brk nm> -u –e <exec grp> -l debug –r
This will reset the trace to 0.
3.From the command line issue the command
mqsireadlog <brk nm> -u –e <exec grp> -o temp.xml
This will read the log to the .xml file
4.Format the log to readable .txt file issue the command
mqsireadlog -i temp.xml –o temp.txt

26. How to use DestinationList

To use the destination list set the property of the output node as follows
Destination Mode : Destination List
Message Context: Pass All
In the compute node set the following property -
SET OutputLocalEnvironment.Destination.MQDestinationList.DestinationData.queueName[1] = V_DestinationQueue;

27. To copy repeating elements from input to output

SET OutputRoot.XML.Output_top.Outfield1.Target[] = (SELECT I FROM InputRoot.XML.Field_top.field1[] AS I );

The next example shows a different way to do the same operation; it produces the same end result.
SET OutputRoot.XML.Output_top.Outfield2.Target[] = InputRoot.XML.Field_top.field1[];

The following example copies across the source element name. Each field1 element is retained as a field1 element under the Target element.
SET OutputRoot.XML.Output_top.Outfield3.Target.[] = InputRoot.XML.Field_top.field1[];

This example is an alternative way to achieve the same result, with field1 elements created under the Target element.
SET OutputRoot.XML.Output_top.Outfield4.Target.*[] = InputRoot.XML.Field_top.field1[];

28. How to use Filter Node

The ESQL code should have the Body. in this case.

CREATE FILTER MODULE multiple_or_single_message
CREATE FUNCTION Main(RETURNS BOOLEAN
          BEGIN
                   IF Body.Reservation.Request = 'M' THEN
                             RETURN TRUE;
                   END IF;
                   IF Body.Reservation.Request = 'S' THEN
                             RETURN FALSE;
                   END IF;
          RETURN UNKNOWN;
END;
END MODULE;

29. Using ORACLE with WBIMB

If you are going to access Oracle databases on AIX or Solaris, you must set up symbolic links:
On AIX:
ln -s <ORACLE_INSTALL_DIR>/lib/libclntsh.a /usr/lib/libclntsh.so

On Solaris:
ln -s <ORACLE_INSTALL_DIR>/lib/libclntsh.so /usr/lib/libclntsh.a
(where <ORACLE_INSTALL_DIR> is the directory in which Oracle is installed on your system).

30. XML.AsIsElementContent

When required to copy the data from an incoming XML as it is to the target here is the way to do it.
SET OutputRoot.XML.Msg.(XML.AsisElementContent) = 'First line' || CAST(0X0A AS CHAR) || 'second line';

31. How to use Throw node

In the properties for the node select the basic and in that enter the following properties-
Message Catalog: Could be blank
Message Number: Give a number
Message Text: ** Invalid request type.  Value must be 'M' (Multiple) or 'S' (Single) **

32. Change the contents from BITSTREAM to XML

Set the string to the contents of the output message, and use a ResetContentDescriptor node to tell WMQI that the message is now XML data.

33.  How to gather broker statistics

Issue the command mqsichangeflowstats VKB2BRK -a -g -j -c active -r -t basic -n basic -o xml to the broker, called VK2BRK, to start collection of the data.
We specified the following options:
·         -a to specify archive mode
·         -g to specify that data should be collected in all execution groups
·         -j to specify that data should be collected for all message flows
·         -c active to turn on the accounting and stats data collection
·         -r to reset the archive log
·         -t basic to specify that basic thread level data is to be recorded
·         -n basic to specify that basic level node data is to be recorded
·         -o xml to publish the output in XML format
To ensure that the required data is being collected, you can use the mqsireportflowstats command. In our case, issue the command mqsireportflowstats VKB2BRK -a -s -g –j
·         -a to specify that details on archive settings were required
·         -s to specify that details on the snapshot settings were required
·         -g to specify that the details for all execution groups were required
·         -j to specify that details for all message flows were required
If you want to stop accounting and statistics, follow the command with the -c inactive option. For example, mqsichangeflowstats VKB2BRK -a -g -j -c inactive -t basic -n basic -o xml.
When accounting and statistics information collection was activated, we requested it in the format of an XML message published using the Publish/Subscribe mechanism. This results in a message being published by the Message Broker to a topic whose name is of the form: $SYS/ Broker/<broker_name>/StatisticsAccounting/<recordType>/<executionGroupLabel>/<messageFlowLabel> The exact topic name under which the information is published depends on the name of the broker, the type of statistics, and the execution group and message flow label values.

34. Create and Deploy bar files from command line

To create a bar file firstly the properties need to be listed and also set. This is done in the following way-
rem Properties for Command Line WBIMB execution
 
set WBIMB_HOME=<the dir location wherw WBIMB is installed>
set WORKSPACE=%WBIMB_HOME%\eclipse\workspace
set BARNAME=C:\temp\deployable.bar
set BARFILES=<location of the ‘.msgflow’ files in workspace ,separeated by a space>
 
Once done,use the following command to create the bar file –
"%WBIMB_HOME%\eclipse\mqsicreatebar.exe" -data %WORKSPACE% -b %BARNAME% -o %BARFILES%
 
The bar file created ,now to deploy the same to the execution group in the broker follow the commands –
set BROKER=<broker name>
set EXECGRP=<execution group name>
set CFGFILE=%WORKSPACE%\Servers\<the .configmgr file >
set BACK=%cd%

35.              Create HTTPRequest

    private void createHTTPNodeOverride(MbElement mbeLocalEnvRoot, MbElement mbeGlobalEnv, String udpEnv, String str_ConfigAPIPrefix) throws MbException{
        try{
           
            MbElement LEDestination = mbeLocalEnvRoot.createElementAsLastChild(MbElement.TYPE_NAME_VALUE,"Destination","");
                   
            MbElement HTTP = LEDestination.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE,"HTTP","");

            HTTP.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE,"RequestURL","http://localhost:8080/");
                   
            HTTP.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE,"Timeout","90");
           
            MbElement RequestLine = HTTP.createElementAsLastChild(MbElement.TYPE_NAME_VALUE,"RequestLine","");

            RequestLine.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE,"RequestURI","CallMe.asp");

            RequestLine.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE,"HTTPVersion","HTTP 1.1");

        } catch (ConfigException ce) {
            throw Utils.createException(this, ce.getErrorNumber(), "", ce.getErrorMessageParameters());
        }
    }

36. How to debug a message flow in WMB 6.1

From the command line execute the following command to set the port to debug -

mqsichangeproperties <broker-name> -e <execution-group-name>  -o ComIbmJVMManager -n jvmDebugPort -v <port-number>

37. Setting up Subscribe using Broker MF

Use the following piece of code to register a subscription and then write the message to SYSTEM.BROKER.CONTROL.QUEUE. The message with following MQRFH2 headers if written to the queue will also do likewise.

SET OutputRoot.MQRFH2.psc.Command  = 'RegSub';
SET OutputRoot.MQRFH2.psc.Topic = 'Stock/Order/#';
SET OutputRoot.MQRFH2.psc.QName = 'MyStocks';
SET OutputRoot.MQRFH2.psc.QMgrName = 'STOCKSQM';

38. ESQL enhancements

Check if the particular node does exist in the incoming logical tree –

if SINGULAR("InputBody"."Lab10"."Catalog"."Name"[]) THEN
  SET TBLNAME = "InputBody"."Lab10"."Catalog"."Name";
ELSE
  SET TBLNAME = 'CATALOG';
END IF;

To write a continue handler so that even if there is an error the flow continues –

DECLARE CONTINUE HANDLER FOR SQLSTATE 'D42S02'
BEGIN
  SET "OutputRoot"."XML"."Lab10Reply"."Items"."Error" = 'Invalid database name';
        END;

To make sure that if there are multiple threads that are running and allow only a single variable access –
BEGIN ATOMIC
               SET FLOW_COUNTER = FLOW_COUNTER + 1;
               SET "OutputRoot"."XML"."Lab10Reply"."Counter" = FLOW_COUNTER;
        END;

39. Timer Nodes

TimeoutNotification node is used to act as the starter for the flow.
TimeoutControl node is used to act as the node that would control how often or when the TimeoutNotification is activated.

Passing the following values to the TimeoutControl notification allow it to control TimeoutNotification –
<TimeoutRequest>
      <Identifier>TimeReq3</Identifier>
      <Action>SET</Action>
      <StartDate>2005-08-25</StartDate>
      <StartTime>NOW</StartTime>
      <Count>6</Count>
      <Interval>5</Interval>
      <IgnoreMissed>TRUE</IgnoreMissed>
      <AllowOverwrite>TRUE</AllowOverwrite>
</TimeoutRequest>

The following activities need to be done –
Identifier is unique across the broker and is coupled with the TimeoutNotification.
Action is generally ‘SET’ to start the activitiy.
StartDate and StartTime can be ignored as it will mean to start immediately.
Count is the number of time that the retry would be done.
Interval in seconds dictates how often it will be done.
IgnoreMissed if TRUE would mean that if the broker was stopped it should be not consider those events. If FALSE all the events when the broker was down will also run.

40. JMS Nodes

Assume there are 3 queue JMS_IN , JMS_OUT and  JMS_DESTINATION .
Make a small change in the JMSAdmin config file that would be in the <IBM\WebSphere MQ Install path>\Java\bin\JMSAdmin.config directory –

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

From the following directory -<IBM\WebSphere MQ Install path>\Java\bin - run the command jmsadmin.bat

Define a Queue Connection Factory with the following command:
DEFINE QCF(JMS_qcf) QMGR(WQM)

Define the Queue Destination with the following command:
DEFINE Q(JMS_Destination) QUEUE(JMS_DESTINATION) QMGR(WQM)

Issue the following command to make sure that the resources do exist –
DISPLAY CTX

The following command can be used to verify the Queue Connection Factory settings:
DIS QCF(JMS_qcf)

The following command can be used to verify the Queue Destination settings:
DIS Q(JMS_Destination)

Use the 3 properties mentioned in here i.e. INITIAL_CONTEXT_FACTORY , PROVIDER_URL and JMS_Destination(QUEUE) in the configuration for the JMSInput and JMSOutput.

41. Data pattern in TDS message

[0-9]{2}   means a 2 byte field compromising of digits.
[^X]{12,23}          The bytes from 12 to 23 any letter except X
[^\r\n]{32}\r\n      means no carriage return\line feed for 32 bytes and then carriage return line feed
[^\r\n]*\r\n          Means no CR\LF and then CR\LF

42. How to stop the HTTPListener

Set the environment variable MQSI_DONT_RUN_LISTENER=y and then start the broker.

43. How to use HTTPInput ,HTTPReply and HTTPRequest node

a.    HTTPInput

The broker runs on the 7080 port. So effectively any request sent to http://localhost:7080/ is meant for broker. In the HTTPInput node the URL selector pointing to /wsdemo2 means that any request coming for http://localhost:7080/wsdemo2 will be picked by the HTTPinput node. This request will be used as the input for further processing. The default tab can be used to mention any messageset properties also.

b.    HTTPReply

As the request comes from web, the HTTPReply node is used to send the reply back to the requester. Before the data is sent to HTTPReply the properties should be set for the request identifier. It is done in the following way.
            SET OutputLocalEnvironment.Destination.HTTP.RequestIdentifier
            = CAST(InputRoot.MQRFH2.usr.RequestIdentifier AS BLOB);

c.    HTTPRequest

Used to call a web service.Make sure that the OutputLocalEnvironment.Destination.HTTP.RequestURL
Is set in the preceding nodes. Even if the HTTPRequest node is updated in the properties tab with the web service pointer still it will not work as the LocalEnvironment property overrides the node properties.

44. How to use Aggregate nodes

The aggregate nodes are used to use the fan-in and fan-out of requests. It can be used to generate data across flow of message/messages. This might be requirement when data needs to be collected across various parts. The flow is as-

d.    AggregateControl

It begins the process of receipt of a request in the input. The ‘Aggregate Name’ property should be set as per requirement. In output there are two connections, the out connection drives the message out from the node. After successful propagation and completion of the node, the control connection then passes the flow to next node.
The outgoing message will be bereft of any MQMD headers. To add them a compute node needs to be added after the control point.

e.    AggregateReply

It is used to form the output before the result is passed on to the AggregateRequest node. The in point is assumed to receive the message and the out point is supposed to propagate the message to the AggregateRequest based in the folder mode of message.Eg. CreditApprovalResponse

f. AggregateRequest

It is used to collect the replies and ‘fan-in’ them to process the flow of the message.So the node succeeding the AggregateRequest will have the incoming message in the format as
InputRoot.ComIbmAggregateReplyBody.CreditApprovalResponse.MRM.Value

45. Using terms in TDS Message Set

Use the following data patterns when building a message set for TDS.Please note that these can be used only in global elements.
]{58}                 Meant for 58 spaces.
.{50}                    Meant for 50 characters from that point on.
T             Meant for the letter ‘T’.
[0-9]{13}  Meant for 13 numeric characters.
[A-Z0-9]{6}           Meant for 6 alphanumeric characters.
[A-Z]{8}[0-9]{9}[ ]            1st 8 alphabets followed by 9 numeric and a space.

46. Arrangement of data in XML message field

CREATE FIELD OutputRoot.XML.General;
CREATE FIRSTCHILD OF OutputRoot.XML.General NAME 'Messagetype' VALUE InputRoot.XML.General.Messagetype;
      
CREATE LASTCHILD OF OutputRoot.XML.General NAME 'Reason';
CREATE FIELD OutputRoot.XML.General.Reason.Status VALUE '0';
             
CREATE LASTCHILD OF OutputRoot.XML.General NAME 'Reference';
CREATE FIELD OutputRoot.XML.General.Reference.Web VALUE InputRoot.XML.General.Reference.Web;
CREATE FIELD OutputRoot.XML.General.Reference.Request VALUE InputRoot.XML.General.Reference.Request;
      
CREATE LASTCHILD OF OutputRoot.XML.General NAME 'Date' VALUE InputRoot.XML.General.Date;

The output message would be like –
<General>
     <Messagetype>1 </Messagetype>
     <Reason>
           <Status>0</Status>
     </Reason>
     <Reference>
           <Web>161565383 </Web>
           <Request>0000 </Request>
      </Reference>
      <Date>00000 </Date>
</General>

47. COALESCE function use

The function is used to set a value or. Consider a string variable as Cstring with no value. Along the way the value is set to the value of another variable. That value may be null or have some. So in case that it is null

Declare cAppendStr char;
set cAppendStr=COALESCE(cAppendStr,'') || 'kishore Raju' ;

48. How to access the DB in AIX

mqsisetdbparms BrokerName -n DataSourceName -u DataSourceUserId -p DataSourcePassword

49. To access an array in XML

Consider you have a input message  like the following-
<Message>
 <BusinessObject>ZMDMFIPARQ01</BusinessObject>
 <Verb>Create119</Verb>
 <ControlRecord>
  <CRField>TABNAM=EDI_DC40</CRField>
  <CRField>MANDT=600</CRField>
  <CRField>DOCNUM=0000000016645328</CRField>
  <CRField>DOCREL=620</CRField>
  <CRField>STATUS=30</CRField>
  <CRField>DIRECT=1</CRField>
  <CRField>OUTMOD=2</CRField>
  <CRField>IDOCTYP=ZMDMFIPARQ01</CRField>
  <CRField>MESTYP=FIPAYM</CRField>
  <CRField>MESCOD=JCT</CRField>
  <CRField>SNDPOR=SAPPRD</CRField>
  <CRField>SNDPRT=LS</CRField>
  <CRField>SNDPRN=PRDCLNT600</CRField>
  <CRField>RCVPOR=PRDMBPORT</CRField>
  <CRField>RCVPRT=LS</CRField>
  <CRField>RCVPRN=PRDEI</CRField>
  <CRField>CREDAT=20050831</CRField>
  <CRField>CRETIM=113843</CRField>
  <CRField>SERIAL=20050831113843</CRField>
 </ControlRecord>
</Message>

Create a reference to the array as follows-

DECLARE RF_CRField REFERENCE TO InputBody.Message.ControlRecord.CRField[1];

            -- Loop through all the CRFields and find the BO Type, Verb, IdocNo and Createdt
                        WHILE LASTMOVE( RF_CRField ) DO
                        IF LEFT(RF_CRField , 6) = 'DOCNUM' THEN
                                     SET CH_DOCNUM = RF_CRField;
                        END IF;
           
                        IF LEFT(RF_CRField , 6) = 'CREDAT' THEN
                                     SET CH_CREDAT = RF_CRField;
                        END IF;
                       
                        IF LEFT(RF_CRField , 6) = 'CRETIM' THEN
                                     SET CH_CRETIM = RF_CRField;
                        END IF;
                        MOVE RF_CRField NEXTSIBLING REPEAT TYPE NAME;                                                          
END WHILE;     

50. How to generate MessageSet documentation

Once the message model has been generated WBIMB allows the user to create documentation that can be used by the Business analyst to examine and study the message set. To go about creating the documentation-
    1. Select the message set for which the documentation needs to be generated, File -> New -> Message Set Documentation.
    2. Select the Message Set and click Next.
    3. Select the folder and then create a new folder with a name in the Message Set folder.

Similarly a XML Schema can also be generated. 

51. How to access DB from ESQL

            To select only one record from DB.

SET OutputRoot.MRM.ProbId = THE (SELECT ITEM T.PROB_ID FROM
Database.PROBLEMS as T
WHERE ((T.PROB_CUST_ID = InputRoot.MRM.CustId) and
(T.PROB_DATE_RAISED = InputRoot.MRM.DateRaised)));

52. How to know MQSI version

Use the following command to know the version of the WBIMB that you are running.
Mqsiservice –v

53. WBIMB v6 some info

·         Starting from MBv6 both the brokers can co exist i.e. MB5 and MB6 can be on the same machine without the need to remove/migrate them. To access the MB6 details a command console has been provided. But from the normal command console all the details will be shown in the normal command window.
·         A java-programming interface is provided that allows it to be programmed using java.
·         New activities that can be done from the command line –
1.    mqsicreateexecutiongroup –b <Broker name> -e <exec group name>
2.    mqsideleteexecutiongroup –b <Broker name> -e <exec group name>
3.    mqsistartmsgflow –b <Broker name> -e <exec group name> -m<flow name>
4.    mqsistopmsgflow –b <Broker name> -e <exec group name> -m<flow name>
·         To migrate any components from lower version to upper version use the MB6 console and then type the command as ‘mqsimigratecomponents <Broker name>‘. This command can in fact take more arguments than broker name alone.
·         Starting from MB6 configuration manager will also have a name. The name can be mentioned when creating the configuration manager.
·         Starting from v6 configuration manager can be backed up and restored on another machine. The new machine must have a blank installation for MBv6 done before hand.
·         Compute node will allow simultaneous different database access.DB2ADMIN
·          
·         To migrate message flows with mapping to version 6  go to the eclipse directory and issue the following command –
mqsimigratemfmaps -p LAB2_MFP2 -data c:\Student\Workspace
after this start the eclipse toolkit and do the select project -> clean project.

54. WBIMB v6 Config mgr backup and restore

Starting from v6 one can backup the configuration manager in a repository and then restore the same on another machine. The syntax for the backup of config mgr is –
mqsibackupconfigmgr configMgrName –d archiveDirectory
[-a archiveName] [-w workpath]

This will create a .zip file with the name supplied in the command. This archive can then be used to restore the configuration manager across any OS system. The syntax for the same would be
mqsirestoreconfigmgr configMgrName –d archiveDirectory
[-a archiveName] [-w workpath]

55. Broker deleted by mqsidelete but not from toolkit

BIP1506E: Queue manager 'njsp_epinet_QM' cannot be associated with broker 'njsp_epinet_bkr'; it may still be in use by another broker 'njsp_epinet_bkr' which is pending deletion.

Broker 'njsp_epinet_bkr' has been removed from the domain of active brokers, although it may still be using its queue manager. It is not possible to associate another broker with the queue manager until the Configuration Manager can confirm that the first broker has tidied up its resources.

In V5 and earlier, delete the broker's SYSTEM.BROKER.ADMIN.QUEUE such that an MQRC 2085 would be thrown when the Config Manager tries to deploy to it.
When you next initiate a deploy to that broker, the Config Manager will pick up the 2085 and permanently tidy up references to the broker.

In V6, use the Config Manager Proxy API Exerciser - connect, right click on the Topology object and select "Remove References to a previously deleted broker". Enter the deleted broker's name or UUID and click OK.

56. To publish multiple topics for the same message

If the input contains many topics that need to be published with the message format as –
<Message_Body>
    <Topic>Topic1</Topic>
    <Topic>Topic2</Topic>
    <Topic>Topic3</Topic>
    <PubContent>Data published to 3 topics</PubContent>
</Message_Body>

One way would be to do the following

CREATE FUNCTION Main(RETURNS BOOLEAN
BEGIN
        DECLARE I INTEGER 1;
        DECLARE J INTEGER CARDINALITY(InputRoot.XML.Message_Body.Topic[]);
WHILE I <= J DO
CALL CopyMessageHeaders();
SET OutputRoot.MQMD.Format='MQHRF2';
SET OutputRoot.MQRFH2.psc.command='Publish';
SET OutputRoot.MQRFH2.psc.Topic =    InputRoot.XML.Message_Body.Topic[I];
SET OutputRoot.XML.a.PubContent = InputRoot.XML.Message_Body.PubContent;
SET OutputRoot.XML.a.CNT = J;
SET I = I + 1;
PROPAGATE;
END WHILE;
RETURN FALSE;
        END;

57. To set up a Oracle configurable properties

From the command line have the following entered as required –
JDBCProviders
  XE
    connectionUrlFormat='jdbc:oracle:thin:system/password@localhost:1521:XE'
    connectionUrlFormatAttr1=''
    connectionUrlFormatAttr2=''
    connectionUrlFormatAttr3=''
    connectionUrlFormatAttr4=''
    connectionUrlFormatAttr5=''
    databaseName='XE'
    databaseType='Oracle'
    databaseVersion='11.0.2.0'
    description='default_Description'
    environmentParms='default_none'
    jarsURL='C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib'
    maxConnectionPoolSize='0'
    portNumber='1521'
    securityIdentity='SXX'
    serverName='localhost'
    type4DatasourceClassName='oracle.jdbc.xa.client.OracleXADataSource'
    type4DriverClassName='oracle.jdbc.OracleDriver'

Also set up the configurable security property as follows, for this the broker needs to be stopped –

mqsisetdbparms %BROKERNAME% -n jdbc::SXX -u user -p pass

mqsicreateconfigurableservice WBRK7 -c JDBCProviders -o ORA_tst_01-n connectionUrlFormat,connectionUrlFormatAttr1,databaseName,databaseType,databaseVersion,jarsURL,portNumber,securityIdentity,serverName, type4DatasourceClassName, type4DriverClassName -v "jdbc:oracle:thin:[user]/[password]@[serverName]:[portNumber]:[connectionUrlFormatAttr1]","HR123","HR123","Oracle","10.2.0.4.0","C:\oracle\product\10.2.0\cl\jdbc\lib","1521","Ora_tst","tstdbr2","oracle.jdbc.xa.client.OracleXADataSource","oracle.jdbc.OracleDriver"

58. To Set up configurable property for JMS Provider eg. JBoss

Before this command is executed, copy all the client jars to the location in the command mentioned in here. This will ensure that the JMSClient in WMB will be able to connect to the JSM queues.

mqsicreateconfigurableservice WBRK7 -c JMSProviders -o JBoss1 -n jarsURL,jmsAsyncExceptionHandling,jndiEnvironmentParms -v C:\IBM\MQSI\7.0\jre16\lib\ext,true,org.jnp.interfaces.NamingContextFactory

C:\IBM\MQSI\7.0>mqsireportproperties WBRK7 -c JMSProviders  -o JBoss -r

JMSProviders
  JBoss
    clientAckBatchSize='0'
    clientAckBatchTime='0'
    initialContextFactory=''
    jarsURL='default_Path'
    jmsAsyncExceptionHandling='true'
    jndiBindingsLocation=''
    jndiEnvironmentParms='default_none'
    nativeLibs='default_Path'
    proprietaryAPIAttr1='default_none'
    proprietaryAPIAttr2='default_none'
    proprietaryAPIAttr3='default_none'
    proprietaryAPIAttr4='default_none'
    proprietaryAPIAttr5='default_none'
    proprietaryAPIHandler='default_none'

BIP8071I: Successful command completion.

C:\IBM\MQSI\7.0>mqsireportproperties WBRK7 -c JMSProviders  -o JBoss -r

JMSProviders
  JBoss
    clientAckBatchSize='0'
    clientAckBatchTime='0'
    initialContextFactory=''
    jarsURL='C:\IBM\MQSI\7.0\jre16\lib\ext'
    jmsAsyncExceptionHandling='true'
    jndiBindingsLocation='jnp://ricwcimdmd1.performance.noname.com:1099'
    jndiEnvironmentParms='org.jnp.interfaces.NamingContextFactory'
    nativeLibs='default_Path'
    proprietaryAPIAttr1='default_none'
    proprietaryAPIAttr2='default_none'
    proprietaryAPIAttr3='default_none'
    proprietaryAPIAttr4='default_none'
    proprietaryAPIAttr5='default_none'
    proprietaryAPIHandler='default_none'

BIP8071I: Successful command completion.

59. To query multiple databases using WBIMB v6

Starting with version 6, WMB allows querying multiple databases from a single compute node. To do this specify the primary DSN on the compute node that will be used in ESQL and then include the other DSN to query the different Database. In this case we are using DSN1 as the primary DSN and specify it in the properties for the compute node, while DSN2 in the compute node will be used as secondary DSN.

            SET Environment.DB.Variables[]  =
(SELECT B.PROJNO ,B.PROJNAME ,B.DEPTNO ,B.RESPEMP ,B.PRSTAFF ,B.PRSTDATE ,  B.PRENDATE   
                         FROM    Database.DSN1.SCHEMA1.TABLE1 AS B);

            SET Environment.DB.Variables[]  =
(SELECT B.PROJNO ,B.PROJNAME ,B.DEPTNO ,B.RESPEMP ,B.PRSTAFF ,B.PRSTDATE ,  B.PRENDATE  
                         FROM    Database.DSN2.SCHEMA2.TABLE2 AS B);

60. To use FileOutput node for FTP

Stop the broker and use the mqsisetdbparms to set the user id and pwd for the connection to FTp server –
Mqsisetdbparms <broker> -n ftp::<identity> - u userid –p password
example - 
mqsisetdbparms IIB9 –n ftp::test -u test -p test

Set a configurable service - 
mqsicreateconfigurableservice IIB9 -c FtpServer -o testserver_testqa -n accountInfo,cipher,compression,connectionType,knownHostsFile,mac,preserveRemoteFileDate,protocol,remoteDirectory,scanDelay,securityIdentity,serverName,strictHostKeyChecking,timeoutSec,transferMode  -v "","","","ACTIVE","","","","FTP","/test","60","test","testserver_ip","","",""

Use the following properties in the FTP tab –
Check the FTP check box
Set the FTP server ip and the port.
Set the identity created from the mqsidbparms command.
Give the absolute directory path to which one has to copy the file.

To dynamically change the location and the security identity of the FileOutput node - 

SET OutputLocalEnvironment.Destination.File.Remote.Server = <<Configurable Service Name>>

61. To carry out activity on database

For normal Insert,Update and Delete statements here is an example -

IF Root.XML.TestCase.Action = ’INSERT’
THEN
INSERT INTO Database.STOCK (STOCK_IDSTOCK_DESCSTOCK_QTY_HELDBROKER_BUY_PRICEBROKER_SELL_PRICESTOCK_HIGH_PRICESTOCK_HIGH_DATESTOCK_HIGH_TIME)
  VALUES (CAST(Root.XML.TestCase.stock_id AS INTEGER),
         Root.XML.TestCase.stock_desc,
         CAST(Root.XML.TestCase.stock_qty_held AS DECIMAL),
         CAST(Root.XML.TestCase.broker_buy_price AS DECIMAL),
         CAST(Root.XML.TestCase.broker_sell_price AS DECIMAL),
         Root.XML.TestCase.stock_high_price,
CURRENT_DATE,
CURRENT_TIME);
ELSEIF
  Root.XML.TestCase.Action = ’DELETE’

  THEN
         DELETE FROM Database.STOCK
WHERE STOCK.STOCK_ID = CAST(Root.XML.TestCase.stock_id AS INTEGER);
  ELSEIF Root.XML.TestCase.Action = ’UPDATE’
  THEN    UPDATE Database.STOCK as A
         SET STOCK_DESC = Root.XML.TestCase.stock_desc
WHERE A.STOCK_ID = CAST(Root.XML.TestCase.stock_id AS INTEGER);
END IF;

To update a table using the 'IN' clause with values from incoming XML message - 

UPDATE Database.SYSTEM.CUSTOMER  
SET NAME = 'never' 

WHERE CUSTOMER.NAME IN (SELECT CUST.Name FROM InputRoot.XMLNSC.Customer[] AS CUST); 

The incoming message loos like this 
<Customer><Name>hello</Name></Customer>

To call a stored procedure. Consider a stored procedure in the ‘SAMPLE’ database taking in 2 parameters one a CHAR and another an ‘INT’ –
           
CREATE PROCEDURE UPDATE_SALARY (IN P1 CHARIN P2 INT)
                        LANGUAGE DATABASE 
                        EXTERNAL NAME "DB2ADMIN.UPDATE_SALARY";        

This procedure will be called as –
CALL UPDATE_SALARY('000010',1);

62. ESQL Code to strip namespace from incoming message

Add Namespace
        DECLARE NM CHAR 'urn:news-com-nz:schema:common:monitor:payment:gateway:echo:v1_0'
        DECLARE BodyRefPtr REFERENCE TO OutputRoot.XMLNSC;
        CALL AddNamespaces(BodyRefPtr,NM);

        CREATE PROCEDURE AddNamespaces(IN StartRefPtr REFERENCEIN NM CHAR)
        BEGIN
               DECLARE FieldRefPtr REFERENCE TO StartRefPtr;
              
               MOVE FieldRefPtr FIRSTCHILD;
               IF LASTMOVE(FieldRefPtrTHEN
                       IF FIELDTYPE(FieldRefPtrIN (0x010000000x03000000THEN
                               SET FieldRefPtr.(XML.NamespaceDecl) = NM;
                               SET FieldRefPtr NAMESPACE = NM;
                       END IF;
               END IF;
              
               WHILE LASTMOVE(FieldRefPtrDO
                       CALL AddNamespaces(FieldRefPtr,NM);
                       IF FIELDTYPE(FieldRefPtrIN (0x010000000x03000000THEN
                               SET FieldRefPtr.(XML.NamespaceDecl) = NM;
                               SET FieldRefPtr NAMESPACE = NM;
                       END IF;
                       MOVE FieldRefPtr NEXTSIBLING;
               END WHILE;
     END;

Remove Namespace
        DECLARE BodyRefPtr REFERENCE TO OutputRoot.XMLNSC;
        CALL StripNamespaces(BodyRefPtr);

        CREATE PROCEDURE StripNamespaces(IN StartRefPtr REFERENCE)
        BEGIN
               DECLARE FieldRefPtr REFERENCE TO StartRefPtr;
              
               MOVE FieldRefPtr FIRSTCHILD;
               IF LASTMOVE(FieldRefPtrTHEN
                       IF FIELDTYPE(FieldRefPtrIN (0x010000000x03000000THEN
                               SET FieldRefPtr.(XML.NamespaceDecl)* = NULL;
                               SET FieldRefPtr NAMESPACE = '';
                       END IF;
               END IF;
              
               WHILE LASTMOVE(FieldRefPtrDO
                       CALL StripNamespaces(FieldRefPtr);
                       IF FIELDTYPE(FieldRefPtrIN (0x010000000x03000000THEN
                               SET FieldRefPtr.(XML.NamespaceDecl)* = NULL;
                               SET FieldRefPtr NAMESPACE = '';
                       END IF;
                       MOVE FieldRefPtr NEXTSIBLING;
               END WHILE;
        END;

63. JAVA Code to strip namespace from incoming message

Add Namespace
        final MbElement mbeOutputRootElement = outMessage.getRootElement().getFirstElementByPath(MbXMLNSC.ROOT_ELEMENT_NAME); 

        addAllNamespacePrefixesAndDeclarations(mbeOutputRootElement,strInputNameSpace);
       
    public void addAllNamespacePrefixesAndDeclarations(final MbElement inElement,final String strInputNameSpace) throws MbException {

        // apply the logic to this first element.
        inElement.setNamespace(strInputNameSpace);
        // if there is a child of this first element, invoke self on that first
        // child.
        final MbElement inElementChild = inElement.getFirstChild();
        if (inElementChild != null) {
            addAllNamespacePrefixesAndDeclarations(inElementChild,strInputNameSpace);
        }
        // if we get to here, there are no more children ...
        MbElement inElementSibling = inElement.getNextSibling();

        // while there is a sibling of this first element, apply the logic to
        // this sibling.

        while (inElementSibling != null) {
            inElementSibling.setNamespace(strInputNameSpace);
            // if there is a child of this element, invoke self on that first
            // child.
            final MbElement inElementSiblingChild = inElementSibling.getFirstChild();
            if (inElementSiblingChild != null) {
                addAllNamespacePrefixesAndDeclarations(inElementSiblingChild,strInputNameSpace);
            }
            inElementSibling = inElementSibling.getNextSibling();
        }
    }


Remove Namespace
        final MbElement mbeOutputRootElement = outMessage.getRootElement().getFirstElementByPath(MbXMLNSC.ROOT_ELEMENT_NAME);

        removeAllNamespacePrefixesAndDeclarations(mbeOutputRootElement);

    public void removeAllNamespacePrefixesAndDeclarations(final MbElement inElement) throws MbException {

        // apply the logic to this first element.
        inElement.setNamespace("");
        // if there is a child of this first element, invoke self on that first
        // child.
        final MbElement inElementChild = inElement.getFirstChild();
        if (inElementChild != null) {
            removeAllNamespacePrefixesAndDeclarations(inElementChild);
        }
        // if we get to here, there are no more children ...
        MbElement inElementSibling = inElement.getNextSibling();

        if (MbXMLNSC.NAMESPACE_DECLARATION == inElement.getSpecificType()) {
            inElement.detach();
        }
        // while there is a sibling of this first element, apply the logic to
        // this sibling.

        while (inElementSibling != null) {
            inElementSibling.setNamespace("");
            // if there is a child of this element, invoke self on that first
            // child.
            final MbElement inElementSiblingChild = inElementSibling.getFirstChild();
            if (inElementSiblingChild != null) {
                removeAllNamespacePrefixesAndDeclarations(inElementSiblingChild);
            }
            inElementSibling = inElementSibling.getNextSibling();
        }
    }

64. How to use JavaCompute node in MB6

To use a JavaCompute node select the node onto the workspace.
Right click on the node and select open java. This will prompt for the project name. Give an appropriate name to it.
Select next and when prompted, give a name to the class.
Choose a template for the java compute node. The template would be generally as for Filter a message, change an incoming message or to create an altogether new message.
Once done a java workspace will open. Make it a point to select the javacompute.jar and japlugin2.jar file as they are primary requirement for developing the flow.
By default the java flow will have extended the ‘com.ibm.broker.javacompute.MbJavaComputeNode’ class in the workspace.

65. How to debug a javacompute node

To debug a javacompute node it needs to be first set up for that as for the port et all.Use the following command from the command console to get it started.

Mqsichangeproperties <BrokerName> -e <Execution group name> -o ComIbmJVMManager –n jvmDebugPort –v <Port Number>

After done the execution group needs to be restarted and to do that issue the following command.

Mqsireload <Broker Name> -e <Execution Group Name>
Update: I have noted that this above activity to set up the jvm debug port is not required with IIB 10.

66. How to call a JAVA procedure from ESQL

Create a ESQL in the toolkit as shown below –

CREATE PROCEDURE myProc1( IN P1 INTEGEROUT P2 INTEGERINOUT P3 INTEGER )
 RETURNS INTEGER
 LANGUAGE JAVA
 EXTERNAL NAME "com.ibm.broker.test.MyClass.myMethod1";

Compile the class file and create the jar file of the .class file.The code will be like this-
           
package com.ibm.broker.test;
class MyClass {
public static Long myMethod1( Long P1, Long[] P2 Long[] P3) { ... }

Assign the .jar file to the CLASSPATH.Stop and start the broker if on UNIX machine and if windows machine then restart the machine.
With the new features of MB6 this feature would not be needed any more as java compute node can now take care of this.

67. Java notations for tree variable

Java accessor from MbMessageAssembly
ESQL field type constant
getMessage().getRootElement()
InputRoot
getMessage().getRootElement().getLastChild()
InputBody
getLocalEnvironment().getRootElement()
InputLocalEnvironment
getGlobalEnvironment().getRootElement()
Environment
getExceptionList().getRootElement()
InputExceptionList

68. Create MQ LocalEnv Destination in Java

a.    Option 1

        final MbXPath destList = new MbXPath(
            "/?^Destination/?^MQ/?^DestinationData/?^queueName[set-value($queueName)]"
        );
        final StringBuilder queueName = new StringBuilder(48);
        queueName.append(runtimeEnvironment);
        queueName.append(DOT);
        queueName.append(strServiceName);
        queueName.append(DOT);
        queueName.append(strOperationName);
        queueName.append(DOT);
        queueName.append(strSourceApplication);
        destList.assignVariable("queueName", queueName.toString().toUpperCase());
        localEnv.evaluateXPath(destList);


b.    Option 2


            // set the MQ destination
            setMQDestinationXPath = new MbXPath("?Destination/?MQ/?DestinationData/?queueName[set-value($queueName)]");
            String queueName = environmentUDP + STR_DOT + userId.getValueAsString() + STR_DOT + serviceName.getValueAsString() + STR_DOT +
                operationName.getValueAsString();

            setMQDestinationXPath.assignVariable("queueName", queueName.toUpperCase());
            outAssembly.getLocalEnvironment().getRootElement().evaluateXPath(setMQDestinationXPath);

69. Create HTTP LocalEnv Destination in Java

   MbElement LEDestination = mbeLocalEnvRoot.createElementAsLastChild(MbElement.TYPE_NAME_VALUE,"Destination","");
   MbElement HTTP = LEDestination.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE,"HTTP","");
   HTTP.createElementAsFirstChild(MbElement.TYPE_NAME_VALUE,"RequestURL",str_HTTPURL);

70. Construct Email request

createEmailBody(mbeOutRootElement);
private void createEmailBody(final MbElement mbeOutRootElement) throws MbException {
        final MbElement mbeOutBLOB = mbeOutRootElement.createElementAsLastChild(MbBLOB.PARSER_NAME);
        final MbElement mbeOutBLOBBLOB = mbeOutBLOB.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, MbBLOB.ROOT_ELEMENT_NAME, null);
        final String meh = "Please do not reply to this Email.";
        final byte[] bodyText = meh.getBytes();
        mbeOutBLOBBLOB.setValue(bodyText);
    }

createEmailAttachment(outAssembly, mbeOutXMLNSC);
    private void createEmailAttachment(final MbMessageAssembly outAssembly, final MbElement mbeOutXMLNSC) throws MbException {
        final MbElement mbeGblBlob = outAssembly.getGlobalEnvironment().getRootElement().createElementAsLastChild(MbBLOB.PARSER_NAME);
        final MbElement mbeGblBLOBBLOB = mbeGblBlob.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, MbBLOB.ROOT_ELEMENT_NAME, null);
        final byte[] btarrpayload = mbeOutXMLNSC.toBitstream(EMPTY_STRING, EMPTY_STRING, EMPTY_STRING, 0, 0, 0);
        mbeGblBLOBBLOB.setValue(btarrpayload);
    }

        final MbElement mbeOutProperties = outMessage.getRootElement().getFirstElementByPath(MbMQMD.ROOT_ELEMENT_NAME);
        final MbElement mbeOutEmailOutputHeader = mbeOutProperties.createElementAfter(MB_OUTPUT_HEADER);
    /**
     *
     * Constructs as next sibling of Properties the follow structure:
     *
     * EmailOutputHeader.To
     * EmailOutputHeader.Cc
     * EmailOutputHeader.Bcc
     * EmailOutputHeader.From
     * EmailOutputHeader.Reply-To
     * EmailOutputHeader.Subject
     */
final MbElement mbeOutLclDestination
        final MbElement mbeOutLclEmail = mbeOutLclDestination.createElementAsLastChild(MbElement.TYPE_NAME, "Email"null);
        createElementFromConfigAPI(shortConfigAPIKey, mandConfig, optConfig, mbeOutLclEmail, "SMTPServer");
        // We don't usually set this, but just incase we ever DID want to use specific credentials
        createOptionalElementFromConfigAPI(shortConfigAPIKey, optConfig, mbeOutLclEmail, "SecurityIdentity");
        // If not set, defaults to text/plain.
        createOptionalElementFromConfigAPI(shortConfigAPIKey, optConfig, mbeOutLclEmail, "BodyContentType");
        //Used only where we want to implement multipart (mixed content) messages e.g. plain text and XML.
        createOptionalElementFromConfigAPI(shortConfigAPIKey, optConfig, mbeOutLclEmail, "MultiPartContentType");
       
        //Email.Attachment Properties. 
        final MbElement mbeOutLclEmailAttachment = mbeOutLclEmail.createElementAsLastChild(MbElement.TYPE_NAME, ATTACHMENT, null);
        createOptionalElementFromConfigAPI(longConfigAPIKey, optConfig, mbeOutLclEmailAttachment, "Content");
        createOptionalElementFromConfigAPI(longConfigAPIKey, optConfig, mbeOutLclEmailAttachment, "ContentType");
        createOptionalElementFromConfigAPI(longConfigAPIKey, optConfig, mbeOutLclEmailAttachment, "ContentName");
        createOptionalElementFromConfigAPI(longConfigAPIKey, optConfig, mbeOutLclEmailAttachment, "ContentEncoding");

71. To iterate incoming message for folders

<LocalEnvironment>
   <SOAP>
                   <Envelope>
                                  <Header>
                                                 <Security>
                                                                <UsernameToken>
                                                                                <Username>S102706</Username>
                                                                                <Password>13WMBIS1</Password>
                                                                </UsernameToken>
                                                                <UsernameToken>
                                                                                <Username>S102706</Username>
                                                                                <Password>13WMBIS1</Password>
                                                                </UsernameToken>
                                                 </Security>
                                  </Header>
                   </Envelope>
   </SOAP>
</LocalEnvironment>

//Added by Godfrey for Multiple user name testing
final MbElement header = outAssembly.getMessage().getRootElement().createElementAsLastChild(MbXMLNSC.FOLDER"Header"null);
final MbElement routing = header.createElementAsFirstChild(MbXMLNSC.FOLDER"Routing"null);
final MbElement security = header.createElementAsLastChild(MbXMLNSC.FOLDER"Security"null);

final MbMessage env = inAssembly.getMessage();
final MbElement InputLocalEnvironment = inAssembly.getLocalEnvironment().getRootElement();
MbElement userName =
    InputLocalEnvironment.getFirstElementByPath("/SOAP/Envelope/Header/Security/UsernameToken");
   
String userID,Password;
                while (userName != null){
                           
                            userID = userName.getFirstChild().getValueAsString();
                                       
                            Password = userName.getLastChild().getValueAsString();
                           
                            userName = userName.getNextSibling();
                            security.createElementAsLastChild(MbXMLNSC.FOLDER, "UserName", userID);
                            security.createElementAsLastChild(MbXMLNSC.FOLDER, "Password", Password);
}   

72. Use ArrayList to create multiple elements in the message and browse them


final List<MbElement> mbeBody = new ArrayList<MbElement>();
final MbElement mbeInputListAccount = mbeInputBody.getFirstElementByPath(INPUTACDTLOUTPUT);
mbeBodyList.add(mbeInputBody);

    private static void createBodyElement(final List<MbElement> mbeBodyList, final MbElement mbeMessage) throws MbException {
        MbElement mbeOutputGetCollDetRespAcList=null;
        MbElement mbeOutputWMEMessageBody=null;
        for (MbElement mbeBody : mbeBodyList) {
            //for first body element create the main tags
            if (mbeOutputWMEMessageBody==null){
                //OutputRoot/Message/Body
                mbeOutputWMEMessageBody = mbeMessage.createElementAsLastChild(MbXMLNSC.FOLDERBODYnull);
                //OutputRoot/Message/Body/GetCollateralDetailsResponse
                final MbElement mbeOutputGetCollDetResp =
                    mbeOutputWMEMessageBody.createElementAsFirstChild(MbXMLNSC.FOLDER"GetCollateralDetailsResponse"null);
                //OutputRoot/Message/Body/GetCollateralDetailsResponse/AccountsList
                mbeOutputGetCollDetRespAcList = mbeOutputGetCollDetResp.createElementAsFirstChild(MbXMLNSC.FOLDER"AccountsList"null);
                final MbElement mbeNSOutput =
                    mbeOutputGetCollDetResp.createElementAsLastChild(MbXMLNSC.NAMESPACE_DECLARATION,"tns",OUTPUTNAMESPACE);
                mbeNSOutput.setNamespace("xmlns");
                mbeOutputGetCollDetResp.setNamespace(OUTPUTNAMESPACE);
                mbeOutputGetCollDetRespAcList.setNamespace(OUTPUTNAMESPACE);
            }
            //point to Body/GetCLLAccountDetailsResponse/GetCLLAccountDetailsOutput
            final MbElement mbeInputListAcount = mbeBody.getFirstElementByPath(INPUTACDTLOUTPUT);
            //OutputRoot/Message/Body/GetCollateralDetailsResponse/AccountsList/Account
            final MbElement mbeOutputGetCollDetRespAcListAcc =
                mbeOutputGetCollDetRespAcList.createElementAsLastChild(MbXMLNSC.FOLDERACCOUNTnull);
            mbeOutputGetCollDetRespAcListAcc.setNamespace(OUTPUTNAMESPACE);
            //Map the incoming message to the output message
            mapSourceToTarget(mbeInputListAcount, mbeOutputGetCollDetRespAcListAcc,OUTPUTNAMESPACE);
        }
    }

73. To generate a list for input folder message in Java

<document>
<chapter title='Introduction'>
Some text.
</chapter>
</document>

MbMessage message = assembly.getMessage();
MbElement root = assembly.getMessage().getRootElement();
  InputRoot.XMLNSC
MbElement document = root.getLastChild().getFirstChild();
  InputRoot.XMLNSC.document
MbElement chapter = document.getFirstChild(); // returns the first chapter
  InputRoot.XMLNSC.document.document


MbMessage msg = assembly.getMessage();
// the following returns a list of all chapters in the document using an XPath
// expression.
List chapters= (List)msg.evaluateXPath("/document/chapter");
MbElement chapter = (MbElement)chapters.get(0); // returns the first chapter


<Create_Book_Order_MSG>
<Customer_ID>0123456789</Customer_ID>
<Order_Date>2002-10-20 12:00:00</Order_Date>
<Airmail>Yes</Airmail>
<Book_Details>
<ISBN>0123456789</ISBN>
<Book_Price>15.99</Book_Price>
<ISBN>1425112342</ISBN>
<Book_Price>7.99</Book_Price>
<ISBN>9736316345</ISBN>

MbElement inputRoot = inMessage.getRootElement();
MbElement inputBody = inputRoot.getLastChild();
MbElement outputRoot = outMessage.getRootElement();
MbElement outputBody = outputRoot.createElementAsLastChild(MbXML.PARSER_NAME);
MbElement bookOrderResponseMsg = outputBody.createElementAsLastChild(MbXML.ELEMENT, "Book_Order_Response_MSG", null);

OutputRoot.XML.Book_Order_Response_MSG

// Customer ID
MbElement inputCustomerIdElement = inputBody.getFirstElementByPath("./Create_Book_Order_MSG/Customer_ID");

bookOrderResponseMsg.createElementAsLastChild(MbXML.ELEMENT, inputCustomerIdElement.getName(), inputCustomerIdElement.getValue());

This will create
OutputRoot.XML.BookOrderResponse.CustomerId    
As well as set the value with MbElement.getValue()

Turn

Parent.SaleList.Invoice.Item
Parent.SaleList.Invoice.Item.Code='00'
Parent.SaleList.Invoice.Item.Code='01'
Parent.SaleList.Invoice.Item.Description='Unreal Tournament 2004'
Parent.SaleList.Invoice.Item.Category='Games'
Parent.SaleList.Invoice.Item.Price='24.99'
Parent.SaleList.Invoice.Item.Quantity='01'
Parent.SaleList.Invoice.Item
Parent.SaleList.Invoice.Item.Code='03'
Parent.SaleList.Invoice.Item.Description='XSLT'
Parent.SaleList.Invoice.Item.Category='Books and Media'
Parent.SaleList.Invoice.Item.Price='19.95'
Parent.SaleList.Invoice.Item.Quantity='01'

to

OutMessage
OutMessage.List
OutMessage.List.Item
OutMessage.List.Item.Description='Unreal Tournament 2004'
OutMessage.List.Item.Category='Games'
OutMessage.List.Item.Price='24.99'
OutMessage.List.Item
OutMessage.List.Item.Description='XSLT'
OutMessage.List.Item.Category='Books and Media'
OutMessage.List.Item.Price='19.95'

MbElement inputBody = inMessage.getRootElement();
MbElement outputRoot = outMessage.getRootElement();
MbElement OutputBody = outputRoot.createElementAsLastChild(MbXMLNSC.PARSER_NAME);
MbElement OutMessage = OutputBody.createElementAsFirstChild(MbXMLNSC.FIELD"OutMessage"null);
MbElement OutList = OutMessage.createElementAsFirstChild(MbXMLNSC.FIELD"List"null);
MbElement OutItem ;
List Description = (List)inputBody.evaluateXPath("/Parent/SaleList/Invoice/Item/Description");
int size = Description.size();
MbElement cursor;
for (int i=0;i< size;i++){
        cursor = (MbElement)Description.get(i);
        OutItem = OutList.createElementAsLastChild(MbElement.TYPE_NAME,"Item",null);
        OutItem.createElementAsLastChild(MbElement.TYPE_NAME,cursor.getName(),cursor.getValueAsString());
        cursor = cursor.getNextSibling();
        OutItem.createElementAsLastChild(MbElement.TYPE_NAME,cursor.getName(),cursor.getValueAsString());
        cursor = cursor.getNextSibling();
        OutItem.createElementAsLastChild(MbElement.TYPE_NAME,cursor.getName(),cursor.getValueAsString());
}






























ICS help

1.    Configuring the WebSphereMQ connector

For configuring the WebSphereMQ connector use the following properties-
ApplicationName     -           WebSphereMQ
MessageFileName   -           Point to the file for the messages
PollEndTime           -           The time when the adapter will stop polling.24hr clock
            PollStartTime                   -           The time from when the adapter will poll.24hr clock
            PollFrequency                  -          The interval time it will poll.
            ArchiveQueue
            Channel  -           ICS queue manager server channel
InputQueue            -           The queue where the message will arrive.
Port                      -           ICS Manager Queue manager port
DataHandlerConfigMO         
DataHandlerMimeType
ReplyToQueue
DataHandlerClassName
HostName
ErrorQueue
UnsubscribedQueue
TraceFileName
InDoubtEvents
InProgressQueue

The BOs that will be used with WebSphereMQ
MO_DataHandler_Default
MO_DataHandler_DefaultDelimitedConfig
MO_DataHandler_DefaultEDIConfig
MO_DataHandler_DefaultFixedWidthConfig
MO_DataHandler_DefaultNameValueConfig
MO_DataHandler_DefaultXMLConfig
MQ_Employee

2.    Running Integrated Test Environment

Once all the components are created and they are ready to be deployed, do the following –
·         Create a user project and update the user project with all the details of the objects
·         Deploy the project to the ICS server.
·         Once done go back to the ‘Integrated Component Library’ and then in the ‘Collaboration Objects’ right click on the object and select the debug in ITE option.
·         Select the project and go ahead. Right click on the blue icons-these are the client simulators for the connectors- and select the option.
·         To connect the connect and start the connector use the connector .con file from the ‘C:\IBM\WebSphereICS\Tools\WSWB212\Workspace’ directory.

3.    How to go about changing the names of the components.

If for some reason the component names are required to be changed it might be required to change the corresponding components configuration also. So here is a checklist of the same when required.

a.    Collaboration Objects

No change is necessary in this case, though the user projects need to be updated.

b.    Maps

In case that the maps are renamed the connector configuration needs to be changed. The other artifacts will remain the same.

c.    Collaboration Templates

In case if the name of the collaboration template is changed, the collaboration object also needs to be created again.

4.    How to go about completing a solution in ICS

To complete a solution in ICS the following steps should be followed diligently.
a.    First create a project in the integrated component library.The name of the library should be unique across the ICS and has not been used anywhere.
b.    Create the BOs for the project. Care should be taken as not to use a name that has been used by other projects and been deployed to the server. If a name is used that is already in the server then redeploying will result in problems with the earlier running component.
c.    Create maps amongst the BOs.Again the names for the maps should be unique in that they have not been used before in the server.
d.    Create the collaboration template with a unique name.
e.    Associate the port with the scenario and the port in and out.
f.     Configure the connector. The connector name should be unique again without any parallel.
g.    Create the collaboration object and then bind them with the connector.Again the name should be unique and not used.
h.    Create a user project and the name for the project should not have been used before. The project should be pointing to the ICL project.
i.      Deploy the project to the ICS server.
j.     Then test of the component by running the collaboration object in “Integrated Test Environment”. This can be done by right click on the ICL Collaboration Object. Either way the test connector can be used also.

5.    Tuning the ICS database

These values should be used as guidelines only for the runtime database that is used for the ICS database –
db2 update db cfg for ISDB using applheapsz 4096
db2 update db cfg for ISDB using dbheap 4800
db2 update db cfg for ISDB using maxappls 1000
db2 update db cfg for ISDB using locklist 400
db2 update db cfg for ISDB using logbufsz 512
db2 update db cfg for ISDB using logfilsiz 4000
db2 update db cfg for ISDB using logprimary 6
db2 update db cfg for ISDB using logsecond 10
db2 update db cfg for ISDB using buffpage 64000
db2 alter bufferpool ibmdefaultbp size -1
db2 update dbm cfg using maxagents 1000
db2 update dbm cfg using mon_heap_sz 1024
db2set DB2_RR_TO_RS=YES
db2set DB2COMM=tcpip

6.    Running web service in ICS

To use web service in ICS it can be used in 2 instances, one with maps and the other with collaboration. Though in both cases the activity editor would be used to call on the web service.
When using in the maps the mapping of data from incoming BO to outgoing BO is used to call on the web service. In this case the triggering BO would be the outbound BO.
In case of the collaboration the data from incoming BO is used to call the web service and the result would then be propagated to the outgoing BO. In this case the triggering BO would be the incoming BO and it will call on the collab and in turn the web service. The result of the web service would be then handed over to the outbound BO.
The web service is in the “My Library” -> “Web Services”. Drag and drop the service on the editor and use the incoming and the outgoing BO.

7.    How to use variables in Collaboration

In a bid to use variables across the collaboration that retain the values.These can be used in the “template definitions” ->“declarations” .The declaration can be declared in the 3rd block. Type would be ‘String’,’int’ et all

8.    How to use the decision node

To use the decision node one has use the variables declared in the collaborations. Before the data comes to collaborations the values need to be set. Once in the decision node use the properties of the decision node to settle the dispute.
In case that we need to use the exception block in the decision making block, the type would be ‘Exception’ for exception and ‘Normal’ for nor mal processing. The condition for exception would be ‘AnyException’. After that the branching would take place.

9.    How to use transaction in collaborations

In the scenario from the service node to action node select the properties. Set the regular service call with the port, verb and BO variable. In case that the transaction needs to be rolled back also select the compensation service call and then enter the port, verb and the BO variable.
In the collaboration object give the object a name and click next.Select the “Effective transaction level “ as “Best Effort” .
In the definitions general tab for the collaboration template select the “Minimum  Transaction Level” as “Best effort” .

10. How to use debugger for collaborations

To use a debugger to know what is going on in the collaboration install the WSAD – I suppose an Eclipse will also do.The ICS server must be started in a debug mode.To do this change the script that starts the server and in the last line just after the “%JCLASSES%” add the following comments –
-Xdebug –Xnoagent –Djava.compiler=NONE –XrunJDWP:transport=dt_socket,server=y,address=8000
Once done now start the WSAD.Make the following changes/creations.
File-> New -> Project
Java -> Project
Give the project a name eg ”ICS Test Project”.
Use default directory NO.
Directory is C:\IBM\WebSphereICS\collaborations\classes
Also add in the java setting –libraries tab add external jars:
C:\IBM\WebSphereICS\lib\ Collabutils.jar , CrossWorlds.jar and CwUtilites.jar
-                      To go about doing that ,start the ICS server from command line.
-                      Start the WSAD and do as creating java project.
-                      Point the  libraries to the .jar files.
-                      Once done all the source code of collab files will be in the menu on the left hand side.
-                      To debug come to the debug perspective,select the debug from the menu and select the “Remote Java Applications” and select the java source code, select the values. Remember for the connection properties the host is localhost of the running interchange server machine and the port is the 8000.This value comes from the script used to start the server
Once done the debug perspective will be filled it is ready and the console will show that the server has started. Open the java source code and one can put a break point in the java code where the debugger will notice.

11. JDBC Connector configuration

To start the JDBC connector -
D:\WebSphereICS\connectors\JDBC. Make the following changes:
– The environment variable CONNDIR, that should have a value of
“%CROSSWORLDS%”\connectors\JDBC
– The environment variable JDBCDRIVERPATH, that should have a value of
C:\SQLLIB\java\DB2Java.zip
– Add C:\SQLLIB\bin to the -Djava.library.path option
– Update the -cp option to refer to CWJDBC.jar.

12. Accesing DB from a collaboration

Assuming that we have a file coming into an inbound connector that would then use a connection to the database, here is the way to go about.
Make a new database connection pool.Enter the options as follows
DBConn

All the terms are self-explanatory
In the collab code one can use the following-

       Vector theRow=null;
       Enumeration theRowEnum=null;
       CwDBConnection conn= getDBConnection("db2connection");
       System.out.println("***conn :"+conn);
       conn.executeSQL("Select * from Customer");
       while(conn.hasMoreRows())
               {
               theRow=conn.nextRow();
        while(conn.hasMoreRows())
        {
               theRow=conn.nextRow();
               System.out.println(triggeringBusObj.getInt("ID"));
               theRowEnum=theRow.elements();
               while (theRowEnum.hasMoreElements())
               {
                      String colValue=(String)theRowEnum.nextElement();
     System.out.println(triggeringBusObj.getInt("ID")+" Column value : "+colValue);
               }
        }
}     

 

Adapter help

1.    Setting up JDBC adapter from reading info from a Table

Create tables namely –
CREATE TABLE WBI_JDBC_EVENT (
EVENT_ID INTEGER NOT NULL PRIMARY KEY,
CONNECTOR_ID VARCHAR(40) ,
OBJECT_KEY VARCHAR(80) NOT NULL ,
OBJECT_NAME VARCHAR(40) NOT NULL ,
OBJECT_VERB VARCHAR(40) NOT NULL ,
EVENT_PRIORITY INTEGER NOT NULL ,
EVENT_TIME TIMESTAMP ,
EVENT_STATUS INTEGER NOT NULL ,
EVENT_COMMENT VARCHAR(100) );

This is for events that take place on the table

CREATE TABLE WBI_JDBC_ARCHIVE (
EVENT_ID INTEGER NOT NULL PRIMARY KEY,
CONNECTOR_ID VARCHAR(40) ,
OBJECT_KEY VARCHAR(80) NOT NULL ,
OBJECT_NAME VARCHAR(40) NOT NULL ,
OBJECT_VERB VARCHAR(40) NOT NULL ,
EVENT_PRIORITY INTEGER NOT NULL ,
EVENT_TIME TIMESTAMP ,
ARCHIVE_TIME TIMESTAMP ,
EVENT_STATUS INTEGER NOT NULL ,
EVENT_COMMENT VARCHAR(100) );

This is for events that are archived.
Create a sequence to maintain the events table entries-
CREATE SEQUENCE WBI_EVENTS_SEQ
    MINVALUE 1
    START WITH 1
    INCREMENT BY 1
    CACHE 20;

Create a trigger on the table from where the data will be taken –

CREATE OR REPLACE TRIGGER CUST_INSRT
    AFTER INSERT ON CUSTOMER
    REFERENCING NEW AS NEWROW
    FOR EACH ROW
   WHEN (NEWROW.CUSTOMER_CD IS NOT NULL)
    BEGIN
        INSERT INTO XWORLDS_EVENTS
   (EVENT_ID,
   CONNECTOR_ID,
   OBJECT_KEY,
   OBJECT_NAME,
   OBJECT_VERB,
   EVENT_PRIORITY,
   EVENT_STATUS,
   EVENT_COMMENT)
   VALUES
   (XWORLDS_EVENTS_SEQ.NEXTVAL,
   'JDBCConnector',
   :NEWROW.CUSTOMER_CD,
   'CUSTOMER',
   'Create',
   1,
   0,
   'TEST');
    END ;

Done to operate.

2.    Setting UP a JCA compliant adapter in WPS using WID

Create a new J2C authentication in WPS Administrative console. Goto ‘Security’ – ‘Secure administration, applications, and infrastructure’ – ‘Java Authentication and Authorization Service’ – ‘J2C authentication data’

CREATE TABLE WSADMIN.WBIA_JDBC_EVENTSTORE
(
EVENT_ID INTEGER  NOT NULL  GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1, NO CACHE ) ,
XID VARCHAR (255) ,
OBJECT_KEY INTEGER  NOT NULL ,
OBJECT_NAME VARCHAR (40)  NOT NULL ,
OBJECT_FUNCTION VARCHAR (40)  NOT NULL ,
EVENT_PRIORITY INTEGER  NOT NULL ,
EVENT_TIME TIMESTAMP  NOT NULL  WITH DEFAULT CURRENT TIMESTAMP ,
EVENT_STATUS INTEGER  NOT NULL , EVENT_COMMENT VARCHAR (100)  ,
CONSTRAINT CC1171598897250 PRIMARY KEY ( EVENT_ID) 
)

The name that is mentioned in the J2C authentication usually comes in the format of ‘widNode/(J2C auth)’. This will be used when creating a BO message from the table and then putting it in the queue as the authentication alias.

Assuming that we have the following table in the database under the schema DB2ADMIN –
CREATE TABLE CUSTOMER
(
pkey VARCHAR(10) NOT NULL PRIMARY KEY,
LName VARCHAR(20),
FName VARCHAR(20),
ccode VARCHAR(10)
);

Create a trigger on that table to populate the event table -
CREATE TRIGGER event_create
AFTER INSERT ON CUSTOMER REFERENCING NEW AS N
FOR EACH ROW MODE DB2SQL
INSERT INTO wbia_jdbc_eventstore (object_key, object_name,
object_function, event_priority, event_status)
VALUES (N.pkey, 'Db2adminCustomerBG', 'Create', 1, 0);

Now if there are any records getting populated in the table for customer, the event table will be populated.

In the WID create a new module for the JDBCOutbound project.
Import the ‘CWYBC_JDBC.jar’  and select the DB option.
Please note that in case of Hierarchical BO options specify the options.

3.    Requisite information for JDBC Adapter using MQ transport

The following queues need to be created and used as part of the activity when using JDBC along with MQ-
AdminInQueue
AdminOutQueue
DeliveryQueue
FaultQueue
RequestQueue
ResponseQueue
SynchronousRequestQueue
SynchronousResponseQueue

DeliveryTransport should be JMS.
MessageFileName should indicate the full path of ‘JDBCConnector.txt’ file.
RepositoryDirectory should mention the directory path where the .XSD files are kept
BrokerType should mention the type of the broker

Connector Specific properties

DatabaseURL jdbc:oracle:thin:@a0300odsp1:1522:ODSP for Oracle
               jdbc:db2:TESTDB for DB2
                   jdbc:ibm-crossworlds:sqlserver://<IP Address>:<Port>;DatabaseName=<DBName> for MS SQL

The format in bold can be used for all the databases without any issue, just substitute the ip address, port and database name for the respective use.


JDBCDriverClass     COM.ibm.db2.jdbc.app.DB2Driver for DB2
                           oracle.jdbc.driver.OracleDriver for Oracle
                           com.ibm.crossworlds.jdbc.sqlserver.SQLServerDriver for MS SQL

RDBMSVendor        MSSQLSERVER
                           DB2
                           ORACLE

4.    Using SAP ODA

After you have selected the IDOC/RFC etc
you get a screen where you can select
- PREFIX
-MODULE
- RELEASE
- UseField name YES/NO

UseField name YES/NO is the one.

5.    ODA configuration

When using the ODA make the following changes to the ‘C:\IBM\WebSphereICS\ODA\JDBC\start_JDBCODA.bat’ file as per the database that one is using-

DB2

Add the following line "C:\Program Files\SQLLIB\java\db2java.zip" to the ‘set DRIVERPATH=’ variable
Make sure that the following line is there - set DRIVERLIB="C:\Program Files\SQLLIB\bin"
In the BO wizard use the following details-
UserName , Password used for the DB access,
DatabaseURL JDBC:HR:<database name>
DatabaseDriver COM.ibm.db2.jdbc.app.DB2Driver

ORACLE
In the BO wizard use the following details-
UserName , Password used for the DB access,
DatabaseURL jdbc.oracle.thin:@localhost:1521:dbname
DatabaseDriver oracle.jdbc.driver.OracleDriver

6.    Requisite information for JText Adapter using MQ transport

As part of configuration of JText the following queues are configured before hand –
AdminInQueue , AdminOutQueue , DeliveryQueue(the queue where the delivery would be made of the message) , FaultQueue , jms.BrokerName (queue manager name) , RequestQueue,ResponseQueue , SynchronousRequestQueue and SynchronousResponseQueue

MO_JTextConnector_Default is the BO that would contain all the details of the MetaData .

 
BO’s that need to be included in the supported BO’s

7.    Ordering the data for RetrieveAll either ASC/DESC

The WebSphere Adapter for JDBC can retrieve the data in either the Ascending/Descending Order by specifying the application-specific information 'OrderBy' and setting this ASI value to either ASC/DESC .

Steps for configure this ASI:
***********************
1) Select the attribute used for Ordering the data and navigate to the attributes 'Properties'
2) In the Properties window, navigate to the Application Info Tab and Select Add to open the 'Extension Window'
3) Select 'JDBC ASI and then 'JDBCAttributtypeMetadata' and Click 'OK'
4) Once done, right click then select 'OrderBy' and specify either ASC/DESC value for this attribute.
The above steps would result in the following ASI text being added to the attribute used for ordering the corresponding Business Object . <jdbcasi:OrderBy>ASC</jdbcasi:OrderBy>

8.    Configuration of Adapter in WPS using WID

It is understood that the entire configuration related to adapter like event tables, triggers have already been done before going ahead with this.
·               Create a adapter module in the WID using the File > New > Module
·               Import the file in the module - Resource Adapters\JDBC\deploy\CWYBC_JDBC.rar and after moving to the J2EE perspective add the external JARS as db2java.zip
·               Move to the Business Integration perspective and File > New > Enterprise Service Discovery and then Select JDBC EMD Adapter and click Next
·               Fill up the nominal details that are common for all the adapters - Jdbc Driver Class: COM.ibm.db2.jdbc.app.DB2Driver
·               Select the tables

               MQ Help

1.    Some Links from Developerworks to help

a.    Auditing the WebSphere MQ environment

b.    The top 15 WebSphere MQ best practices

c.    Integrating WebSphere MQ services with WebSphere Service Registry and Repository

http://www.ibm.com/developerworks/websphere/library/techarticles/1110_xu2/1110_xu2.html

d.  Mission:Messaging: End-to-end encryption with WebSphere MQ Advanced Message Security

http://www.ibm.com/developerworks/websphere/techjournal/1011_mismes/1011_mismes.html

e.    Processing messages with the WebSphere Application Server V7 and V8 WebSphere MQ messaging provider activation specifications

http://www.ibm.com/developerworks/websphere/library/techarticles/1110_titheridge/1110_titheridge.html

f.     Using the Dead Letter Queue Handler in WebSphere MQ

http://www.ibm.com/developerworks/websphere/library/techarticles/1204_gupta/1204_gupta.html

g.    Mission:Messaging: Easing administration and debugging with circular queues

http://www.ibm.com/developerworks/websphere/techjournal/1103_mismes/1103_mismes.html

h.    Customizing file transfers using Ant scripts with WebSphere MQ File Transfer Edition

http://www.ibm.com/developerworks/websphere/library/techarticles/1206_thambrahalli/1206_thambrahalli.html

i.     The top 15 WebSphere MQ best practices

j.     One-to-many file transfers using WebSphere MQ File Transfer Edition

 

k.    Configuring and tuning WebSphere MQ for performance on Windows and UNIX

l.     Test XML messages over WebSphere MQ with Rational Performance Tester

http://www.ibm.com/developerworks/rational/library/xml-messages-websphere-mq-performance-tester-1/index.html
http://www.ibm.com/developerworks/rational/library/xml-messages-websphere-mq-performance-tester-2/index.html
http://www.ibm.com/developerworks/rational/library/xml-messages-websphere-mq-performance-tester-3/index.html

2.    MQ 6 Features

·         MQ 6 allows views to be customized so that viewer can see only queues with messages, with certain number of messages and like. The same can be extended to other aspects like channels, connections and like.
·         A services panel now allows services to be started on QM start or stop.Services will be like start channel,start server connection.
·         Allows one to compare a particular utility with the default template.Right click on the created queue and then select compare.Using the knob with ‘…’ select the template you want to compare with.
·         Accounting ,statistics and monitoring is allowed in MQ6.To set it on right click on the QMgr and then statistics, accounting and online monitoring.To take the accounting and statistics use ‘amqsmon –m QMGR –t statistics/accounting’ depending upon the required.QMgr monitoring for Q and CHL is not set by default and should be done only when required.
·         Message compression is also possible between 2 QMgrs.To do this change the options on the Sender channel from message compression to RLE,ZLIBHIGH or ZLIPFAST.Remember to make similar changes on the receiver for header compression to SYSTEM and message compression to ANY

3.    MQ 6 SSL configuration


Suppose there are two Q Mgrs QM1 and QM2 then create the normal scenario of creating a sender and a receiver channel for each of the Q Mgrs to communicate with each other in the following way –

        QM1                              QM2
            Sender              TO.QM2                          TO.QM1
            Receiver            TO.QM1                          TO.QM2

            Create a key repository for both the queue managers as follows –
            QM1      -           C:\IBM\WMQ\Qmgrs\QM1\ssl\key.kdb
            QM2      -           C:\IBM\WMQ\Qmgrs\QM2\ssl\key.kdb
            Create a self signed certificate with the naming convention as follow –

            QM1      -           ibmwebspheremqqm1
            QM2      -           ibmwebspheremqqm2

Extract the copy of certificate from certificate in the “.arm” format and then import the same into the corresponding  queue manager and then start the channel with ssl configuration as “NULL_SHA”

Operational Decision Manager Help

1.    Some Links from Developerworks to help

a.    Creating a Decision Server Events runtime in WebSphere Operational Decision Management V7.5, Part 1: Configuring a standalone environment

b.    Creating a Decision Server Events runtime in WebSphere Operational Decision Management V7.5, Part 2: Configuring a highly available and scalable environment

c.    Installing and configuring an IBM Operational Decision Management golden topology

d.    Installing and setting up WebSphere Operational Decision Management (WebSphere ODM Information Center)

e.    Overview of ILOG JRules and WebSphere Process Server integration

BPM Help

1.    Some Links from Developerworks to help

a.    Setting up a clustered topology for IBM Business Process Manager V7.5, Part 1: A step-by-step guide for BPM Standard

b.    Using the service integration bus link in WebSphere Application Server to route messages from a local queue to a remote queue

c.    WebSphere Process Server database configuration made easy Using the database design tool

d.    Invoking a process deployed in IBM Business Process Manager V7.5 using WebSphere MQ

e.  Basic steps for clustering WebSphere Process Server

f.    Configuring WebSphere Business Events to use WebSphere MQ as the messaging provider