http://www.ibm.com/developerworks/websphere/library/techarticles/0802_dunn/0802_dunn.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0804_squibb/0804_squibb.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0601_cox/0601_cox.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0809_kudikala/0809_kudikala.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0710_piatek/0710_piatek.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0711_jain/0711_jain.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0505_storey/0505_storey.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0608_piper/0608_piper.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0808_lucas/0808_lucas.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0805_coleman/0805_coleman.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0810_zhang/0810_zhang.html
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
http://www.ibm.com/developerworks/websphere/library/techarticles/0608_braithwaite/0608_braithwaite.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0806_mcmullan/0806_mcmullan.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0603_schutz/0603_schutz.html
http://www.ibm.com/developerworks/websphere/library/techarticles/1212_hart/1212_hart.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0912_nagchowdhury/0912_nagchowdhury.html
http://www.ibm.com/developerworks/websphere/library/techarticles/1105_ghosh/1105_ghosh.html
http://www.ibm.com/developerworks/websphere/library/techarticles/0912_lucas/0912_lucas.html
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
http://www.ibm.com/developerworks/websphere/library/techarticles/1208_soultan/1208_soultan.html
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
###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"
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.
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>
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”
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(ptrException) DO
-- 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 insertText= insertText || ':' || ptrException."Insert"[count].Text;
set count = count + 1;
end while;
END WHILE;
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.
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.
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.
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
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';
IF (EXISTS(Environement.variables.CornerstonePartyID)=FALSE OR
EXISTS(Environement.variables.PartyObject)=FALSE OR
EXISTS(Environement.variables.Session)=FALSE) THEN
THROW USER EXCEPTION VALUES ('Environment variables are not set');
END IF;
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 );
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);
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>
DECLARE brw NAMESPACE ’http://www.ibm.com/Borrowed’;
SET OutputRoot.MRM.brw:Borrowed.VideoTitle = ’MRM Greatest Hits’;
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.
SET OutputRoot.MRM.Elem2.Child1 VALUE = NULL;
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;
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;
From the toolkit ,select EDIT-> Content Assit.
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
To know the execution groups that have been deployed in the broker use the following command –
mqsibrowse <BROKER NAME> -t BROKERAAEG
To know the topics that have been published as well as subscribed use the following command-
mqsibrowse <BROKER NAME> -t BSUBSCRIPTIONS
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
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;
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[];
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;
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).
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';
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) **
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.
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.
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%
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());
}
}
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>
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';
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;
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.
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.
[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
Set the environment variable MQSI_DONT_RUN_LISTENER=y and then start the broker.
43. How to use HTTPInput ,HTTPReply and HTTPRequest node
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.
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);
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.
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-
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.
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
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' ;
mqsisetdbparms BrokerName -n DataSourceName -u DataSourceUserId -p DataSourcePassword
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;
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-
- Select the message set for which the documentation needs to be generated, File -> New -> Message Set Documentation.
- Select the Message Set and click Next.
- 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.
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)));
Use the following command to know the version of the WBIMB that you are running.
Mqsiservice –v
· 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.
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]
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.
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;
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.
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);
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>>
For normal Insert,Update and Delete statements here is an example -
IF Root.XML.TestCase.Action = ’INSERT’
THEN
INSERT INTO Database.STOCK (STOCK_ID, STOCK_DESC, STOCK_QTY_HELD, BROKER_BUY_PRICE, BROKER_SELL_PRICE, STOCK_HIGH_PRICE, STOCK_HIGH_DATE, STOCK_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 CHAR, IN P2 INT)
LANGUAGE DATABASE
EXTERNAL NAME "DB2ADMIN.UPDATE_SALARY";
This procedure will be called as –
CALL UPDATE_SALARY('000010',1);
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 REFERENCE, IN NM CHAR)
BEGIN
DECLARE FieldRefPtr REFERENCE TO StartRefPtr;
MOVE FieldRefPtr FIRSTCHILD;
IF LASTMOVE(FieldRefPtr) THEN
IF FIELDTYPE(FieldRefPtr) IN (0x01000000, 0x03000000) THEN
SET FieldRefPtr.(XML.NamespaceDecl) = NM;
SET FieldRefPtr NAMESPACE = NM;
END IF;
END IF;
WHILE LASTMOVE(FieldRefPtr) DO
CALL AddNamespaces(FieldRefPtr,NM);
IF FIELDTYPE(FieldRefPtr) IN (0x01000000, 0x03000000) THEN
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(FieldRefPtr) THEN
IF FIELDTYPE(FieldRefPtr) IN (0x01000000, 0x03000000) THEN
SET FieldRefPtr.(XML.NamespaceDecl)* = NULL;
SET FieldRefPtr NAMESPACE = '';
END IF;
END IF;
WHILE LASTMOVE(FieldRefPtr) DO
CALL StripNamespaces(FieldRefPtr);
IF FIELDTYPE(FieldRefPtr) IN (0x01000000, 0x03000000) THEN
SET FieldRefPtr.(XML.NamespaceDecl)* = NULL;
SET FieldRefPtr NAMESPACE = '';
END IF;
MOVE FieldRefPtr NEXTSIBLING;
END WHILE;
END;
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();
}
}
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.
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.
Create a ESQL in the toolkit as shown below –
CREATE PROCEDURE myProc1( IN P1 INTEGER, OUT P2 INTEGER, INOUT 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.
Java accessor from MbMessageAssembly
|
ESQL field type constant
|
getMessage().getRootElement()
|
InputRoot
|
getMessage().getRootElement().getLastChild()
|
InputBody
|
getLocalEnvironment().getRootElement()
|
InputLocalEnvironment
|
getGlobalEnvironment().getRootElement()
|
Environment
|
getExceptionList().getRootElement()
|
InputExceptionList
|
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);
// 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);
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);
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");
<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);
}
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.FOLDER, BODY, null);
//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.FOLDER, ACCOUNT, null);
mbeOutputGetCollDetRespAcListAcc.setNamespace(OUTPUTNAMESPACE);
//Map the incoming message to the output message
mapSourceToTarget(mbeInputListAcount, mbeOutputGetCollDetRespAcListAcc,OUTPUTNAMESPACE);
}
}
<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());
}
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
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.
No change is necessary in this case, though the user projects need to be updated.
In case that the maps are renamed the connector configuration needs to be changed. The other artifacts will remain the same.
In case if the name of the collaboration template is changed, the collaboration object also needs to be created again.
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.
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
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.
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
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.
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” .
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.
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.
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
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);
}
}
}
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.
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.
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
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.
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
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
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>
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
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
http://www.ibm.com/developerworks/websphere/library/techarticles/1110_titheridge/1110_titheridge.html
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
http://www.ibm.com/developerworks/websphere/library/techarticles/1206_thambrahalli/1206_thambrahalli.html
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
· 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
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”
e. Overview of ILOG JRules and WebSphere Process Server integration