Sunteți pe pagina 1din 47

MB transactionallity

MB node types
Amunt! Top Amunt!
Built-in nodes (v 6.1)
AggregateControl node
AggregateReply node
AggregateRequest node
Check node
Collector node
Compute node
Database node
DatabaseRetrieve node
DatabaseRoute node
DataDelete node
DataInsert node
DataUpdate node
EmailOutput node
EndpointLookup node
Extract node
FileInput node - retrieves data from a local or remote file system
FileOutput node - outputs data to a local or remote file system
Filter node
FlowOrder node
HttpInput node
HttpReply node
HttpRequest node
Input node
Java Compute node
JMSInput node
JMSMQTransform node
JMSOutput node
JMSReply node
Label node
Mapping node
MQeInput node
MQeOutput node
MQGet node
MQInput node
MQJMSTransform node
MQOptimizedFlow node
MQOutput node
MQReply node
Output node
Passthrough node
PeopleSoftInput node
PeopleSoftRequest node
Publication node
Real-timeInput node
Real-timeOptimizedFlow node
RegistryLookup node
ResetContentDescriptor node
Route node
RouteToLabel node
SAPInput node
SAPRequest node
SCADAInput node
SCADAOutput node
SiebelInput node
SiebelRequest node
SOAPAsyncRequest node
SOAPAsyncResponse node
SOAPEnvelope node
SOAPExtract node
SOAPInput node
SOAPReply node
SOAPRequest node
Throw node
TimeoutControl node
TimeoutNotification node
Trace node
TryCatch node
TwineballInput node
TwineballRequest node
Validate node
Warehouse node
XSLTransform node
New Web services nodes :

Provider nodes (SOAPInput, SOAPReply)


Consumer nodes (SOAPRequest, SOAPAsyncRequest, SOAPAsyncResponse)
Helper nodes (SOAPExtract, SOAPEnvelope)
WebSphere Service Registry and Repository :

EndpointLookup
RegistryLookup
Routing :

DatabaseRetrieve -- to ensure that information in the message is up-to-date.


DatabaseRoute and Route -- to direct messages down different paths of a message
flow based on certain criteria.
Collector -- to create a message collection from one or more sources based on
configurable criteria.
WebSphere Adapter nodes :

PeopleSoftInput
PeopleSoftRequest
SAPInput
SAPRequest
SiebelInput
SiebelRequest
File nodes :

FileInput
FileOutput
Transport nodes

JMSReply
EmailOutput
New and enhanced nodes in MB V6.1

Amunt! Top Amunt!


Node types
Use the Check node to compare the structure of a message arriving on its input
terminal with a message structure definition that you supply when you configure the
Check node.
messagebroker Message Flows, page 302 [312 of 556]

Use the Filter node to route a message according to message content.

messagebroker Message Flows, page 326 [336 of 556]

A Compute node takes as input a message tree (called InputRoot) and outputs a
different message tree (called OutputRoot). Notice that InputRoot is read-only and
therefore cannot be modified in place.

HTTPin & HTTPout nodes allow the CGI world to talk to "c" programs.

SOAPin & SOAPreply nodes allow to talk to the WebServices world - mind NameSpace(s)
and Encoding

Trace node : where to send its output ( diferent at Development and Production ).
When the BAR file is generated, select the "Configure" bottom flap and enter the
"File Path" property. If empty, does it mean "no trace" ?

Other nodes :

SendMailPlugIn - support pack IA07.


A xml tag with the error message is added to the original message.
z/OS File Adapter - support pack IA11.
WS MB Reference + Built-in nodes

local tkt help

Amunt! Top Amunt!


Providing input to a message flow
The type of input node that is used in a message flow depends on the type of
application that sent the message to the broker:

If the message flow gets the messages from the business application by means of a
WebSphere MQ queue, use an MQInput node.
El nico queue manager que el MQInput node puede usar es el que usa el Broker. Por
eso no se puede especificar otro. Gracias, Emir !

If the messages are sent to broker by an MQe application, use an MQeInput node.
If the messages are sent by a telemetry device, use a SCADAInput node.
If the messages are sent by a Web services client, use an HTTPInput node.
If the messages are sent by a JMS or multicast application, use a Real-timeInput
node or a Real-timeOptimizedFlow node.
If the message flow is to be reused as part of one or more other message flows, use
an Input node.

MQInput
JMSInput
HTTPInput
SOAPInput
SAPInput
Timer node
WBI-MB Basics, SG24-7090, page 125 [139 of 262]

If the incoming message has an MQRFH2 header, you do not have to set values for the
Default properties because the values can be derived from the <mcd> folder in the
MQRFH2 header.
If you set values, and those values differ from those in the MQRFH2 header, the
MQRFH2 header values take precedence.
messageBroker_Message_Flows, page 359 [369 of 556]

MQInput Node Properties.

Message Domain
Message Set
Message Type
Message Format
Topic
Each input node in a message flow causes the broker to start a separate thread of
execution. Including more than one input node might improve the message flow
performance.

Message Flows, page 68 [76/1020]

Message Domain types


In Message Domain, select the name of the parser that you are using from the drop-
down list.

MRM
XML
XMLNS
XMLNSC
JMSMap
JMSStream
MIME
BLOB (same as blank)
IDOC
DFDL {mb v8}
Body is equivalent to Root followed by the parser name (for example, Root.XML),
which you can use if you prefer.

Domain errors
If there is a "domain" versus "received message format" mismatch, you can see in
trace:

UnknownParserName = 'MQSTR'
Invalid Wire format retreived
Message Set
Que es ? Que proporciona al fluxe ?

A Message Set corresponds to CICS Copy Book or (Siebel) Web-Service WSDL

In older versions (WMB V7 and below), the primary way general text and binary
messages were modeled and parsed was through a container called a message set and
associated 'MRM' parser. Since WMB V8, and including IBM Integration Bus, such
messages are modeled and parsed using a new open technology called DFDL from the
Open Grid Forum. This is IBM's strategic technology for modeling and parsing
general text and binary data. The MRM parser and message sets remain a fully
supported part of the product; in order to use message sets, a developer must
enable them as they are disabled by default to encourage the adoption of the DFDL
technology.

wiki

Message Set support pack


IA96: WebSphere BI Message Broker - Message Set Tutorial (Article). This SupportPac
shows how to develop and exercise message sets in WebSphere Business Integration
Message Broker version 5.

Recuperaci d'errors
Quan en un fluxe, al que hem entrat mitjanant un node MQInput, hi ha un problema
(as THROW), es torna al node d'entrada, es recupera el missatge inicial, i es surt
pel pin Catch, mantenint l'entorn, on s'ha enmagatzemat la ra del error. Es posa
un "Trace" node i desprs

MQOutput amb clcul del dest via Oracle + DestinationList


MQOutput a una cua fixe de "problemes".
Publish del problema, i que l'agafi qui vulgui
Ver Throw.
Amunt! Top Amunt!
Getting output from a message flow
The output node that is used in a message flow depends on the type of application
that receives the message from the broker:

If the message flow puts the message to the application by means of a WebSphere MQ
queue, use an MQOutput node.
If you want the message flow to put different messages on different WebSphere MQ
queues, depending on the queue name in the Reply-to queue field of the message
header WebSphere MQ, use an MQReply node. Using the MQReply node means that the
name of the output queue is not hardcoded in the message flow.
If the messages are received by a telemetry device, use a SCADAOutput node.
If the messages are received by a Web services client, use an HTTPReply node.
If the message flow interacts with a Web services client, use an HTTPRequest node.
If the messages are received by a JMS or multicast application, use a Real-
timeOptimizedFlow node. This node performs as both an input and an output node.
If the message flow is to be reused as part of one or more other message flows, use
an Output node.
If you want to distribute the messages, using Publish/Subscribe, to many unknown
applications that have subscribed to receive the data, use a Publication node.
WBI-MB Basics, SG24-7090, page 126 [140 of 262]

Petit dubte :
Les propietats del nus de sortida tenen dos camps : queue manager name i queue
name. Que tinc que definir al qmgr local si vull que el missatge se'n vagi a un
qmgr remot (a una cua especifica) ?
O a l'inrevs : si vull que vagi a un qmgr remot, puc especificar aqui una local
"remota" ?

Soluci :

podem no-posar queue manager i posar com a cua una QUEUE REMOTE
podem posar queue manager (remot) i nom de cua (remota), pero llavors haurem de
definir al queue manager local una cua de transmissi que es digui com el queue
manager remot i que estigui assignada a un canal que porti cap al queue manager
remot on estigui la esmentada cua. [Emir, 26-07-2006]
( SAG_BRK.default )
Unable to open queue ''Qsale'' on WebSphere MQ queue manager ''QMEMIR'':
completion code 2; reason code 2087.
No usar nunca el campo QMN - permite movilidad de los flujos.
MQ Output node + "Advanced" settings :
Select the Destination Mode from the drop-down list. This identifies the queues to
which the output message is put.

Queue Name. The message is sent to the queue named in the Queue Name property. The
properties Queue Manager Name and Queue Name (on the Basic tab) are mandatory if
you select this option. This is the default.
Reply To Queue. The message is sent to the queue named in the ReplyToQ field in the
MQMD.
Destination List. The message is sent to the list of queues named in the
LocalEnvironment (also known as DestinationList) associated with the message.
MQoutput calculado
Si al nodo MQoutput (Properties, Advanced) le ponemos "Destination mode :=
Destination List", entonces podemos hacer este clculo :

SET OutputLocalEnvironment.Destination.MQ.DestinationData[I].queueName =
Environment.IMI.Query[I].ColaSalidaPet ;
Compte : el node "Compute" ha de tenir a les seves propietats Compute mode =
LocalEnvironment ! Otherwise veurem aquest missatge a la llista de Events:

-- An MQ output node with the "Destination Mode" property set to "list" received a
message
-- but there was no valid distribution list, that is, it did not contain a
"Destination" folder in turn containing an "MQ" folder.
Amunt! Top Amunt!
Dynamically routing messages
To verify that the structure of a message is correct for subsequent processing, use
the Check node.
To perform a Boolean filter on a message so that if it matches the rule the message
takes one route through the message flow, and if it does not match the rule the
message takes another route through the message flow, use the Filter node.
To force messages to be processed in one way and then processed in a second way,
use the FlowOrder node.
To define a number of alternative destinations to which messages can be sent,
depending on the message header, use a Label node for each destination, and a
RouteToLabel node to determine which Label node a message must be sent to.
To change the message properties before the message is parsed again by nodes
downstream in the message flow, use the ResetContentDescriptor node.
WBI-MB Basics, SG24-7090, page 129 [143 of 262]

A key component of the broker architecture will be the basis on which routing
decisions are made.

B2B Integration using MQ and MQSI, SG24-6010, page 210 [234 of 372]

Message Routing basic sample


CREATE FILTER MODULE afegir1_Filter

CREATE FUNCTION Main() RETURNS BOOLEAN


BEGIN

DECLARE MSG_SRC CHAR ;

SET MSG_SRC = cast(substring(Root.BLOB.BLOB FROM 2 FOR 1) \\


as CHAR CCSID Root.MQMD.CodedCharSetId);

IF ( MSG_SRC = 'A' ) THEN


RETURN TRUE ;
END IF ;

RETURN FALSE ;

END ;

END MODULE ;
Para comparar en hexadecimal se usa:
IF ( MSG_SRC = X'41' ) THEN
RETURN TRUE ;
Pero hay que decir que escrito as el flow no funciona en EBCDIC. El cdigo
anterior (CAST con CCSID) asegura la portabilidad del cdigo.

Si el mensaje es <ab>A</ab>
Como BLOB, substring(Root.BLOB.BLOB FROM 5 FOR 1) da 'A' (char 5-a posicin).
Como XML, hay que usar IF Root.XMLNSC.ab = 'A'
Routing to a Label
in the Compute node, code :
CREATE COMPUTE MODULE DecideOnQuery
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputRoot = InputRoot;
IF InputRoot.XML.PassengerQuery.ReservationNumber <> '' THEN
SET
OutputLocalEnvironment.Destination.RouterList.DestinationData[1].labelname =
'SinglePassenger';
ELSE
SET
OutputLocalEnvironment.Destination.RouterList.DestinationData[1].labelname =
'AllReservations';
END IF;
RETURN TRUE;
END;
END MODULE;
Compute.Out -> RouteToLabel node In
RouteToLabel is EMPTY
Label node 'Label Name := SinglePassenger ;'
Label node 'Label Name := AllReservations ;'
URL

When you use RouteToLabel and Label, you must include a Compute node that
determines, using some combination of message content, database content, and ESQL
logic, how messages are to be processed next. Configure the Compute node to create
a destination list (within the DestinationList folder in the LocalEnvironment
subtree) that contains the destination for each message, specified as the LabelName
of a Label node. The Compute node passes the message to the RouteToLabel node,
which reads the destination list and propagates the message to those destinations.

"Message Flows", page 71 [79/1020]

Amunt! Top Amunt!


User-defined extensions in the runtime environment
Before you design and implement user-defined extensions, you should familiarize
yourself with the core components and ensure you understand the basic WebSphere
Business Integration Message Broker runtime architecture.
You should ensure that you are familiar with the following runtime components and
concepts:

Runtime environment
Broker domain
Configuration Manager
Broker
Execution group
Execution model on page 57
You should also make sure you understand the following concepts:
message flows
the logical message tree
how the message tree is populated
messagebroker_User_Defined_Extensions.pdf, page 56 [64 of 212]

Compiling user-defined extension


url

Amunt! Top Amunt!


Modelling and Parsing Business Data
(short) Introduction to DFDL

Parser
El parser construye un "syntax tree". Ejemplo simple con XML - si el mensaje que
llega al MQ Input node es:

<msg><a>11111</a><b>22222</b></msg>
El parser le permite al ESQL usar estas referencias:

Root.XMLNSC.msg.a (contiene '11111').


Root.XMLNSC.msg.b (contiene '22222').
Y si el message flow ejecuta esto:

set OutputRoot.XMLNSC.msg.c = '33333';


Identifier "OutputRoot" cannot be resolved.
El mensaje de salida sera:

<msg><a>11111</a><b>22222</b><c>33333</c></msg>
El parser hace dos cosas:

construye el "syntax tree" (entrada)


reconstruye el mensaje a partir del "syntax tree" (salida)
DFDL domain and parser
developerWorks :

message modeling : Creating a DFDL CSV message model, also Creating a DFDL Text
(TDS) message model
Creating and testing message models for C and COBOL using DFDL
DFDL is not a data format - it is a language for describing data formats

DFDL is an open standard, hosted by the Open Grid Forum, OGF

Introduction to DFDL

Quan escullo "DFDL" com a "Message Domain", em demana un "Message" - "select a


message from a DFDL schema file in a library"

Soluci : "New" + "Message Model" - Message model sirve tanto para xsd como para
dfdl.

Difference between MRM and DFDL parser


MRM - Message Repository Manager (Supported only in Message Broker)
DFDL - Data Format Description Language (Introduced in MB 8.0 as a new Parser and
Domain)

Standard:
MRM- Proprietary standard
DFDL- Open standard (like WSDL)
Usage:
MRM - Used only in message broker
DFDL - Can be used any product as it is Open standard and Message Broker is the 1st
software product that supports DFDL in WebSphere family.
Testing message model:
MRM - Can't test the modeling without deploying message set and flow that uses it
DFDL - Can be tested without deploying the messaging model (WMB8 toolkit has DFDL
tester)
Performance:
Performance of DFDL parser is much better than MRM
Migration:
MRM - Can't migrate or share message modeling to any other software products.
DFDL - Can migrate or share message modeling to any other software products.
url

LocalEnvironment tree structure


This tree is always present in the input message: an empty LocalEnvironment tree is
created when a message is received by the input node.

Variables
This subtree is optional. If you create local environment variables, you are
recommended to store them in a subtree called Variables. It provides a work area
that you can use to pass information between nodes. This subtree is never inspected
or modified by any supplied node.
Variables in the local environment can be changed by any subsequent message
processing node, and persist until the message flow goes out of scope and the node
that created it has completed its work and returns control to the previous node.
The variables in this subtree are only persistent within a single instance of a
message flow. If you have multiple instances of a message passing through the
message flow, and need to pass information between them, you must use an external
database.

Destination

Written destination

Para poder modificar el Local Environment, hay que copiarlo (de Input -read only -
a Output).

When the message flow processing is complete, the LocalEnvironment tree is


discarded.

Environment tree structure


The Environment tree is a part of the logical message tree in which you can store
information while the message passes through the message flow.

This tree is always present in the input message; an empty Environment tree is
created when a message is received and parsed by the input node. You can use this
tree as you choose, and create both its content and structure.

The Environment tree differs from the LocalEnvironment tree in that a single
instance of it is maintained throughout the message flow.
No hace falta copiarlo. Pero se recibe un Environment vacio con cada mensaje.

LocalEnvironment vs Environment
LocalEnvironment => MQ and MB.

Environment => user.

Both are message-related !


User Defined Properties
A user-defined property (UDP) is a variable that is defined in your ESQL program by
specifying the EXTERNAL keyword on a DECLARE statement. You can define external
variables only at the module and schema level.

Before you deploy the message flow that uses the UDP, you can change the value of
the UDP by using the Broker Archive editor. A deployment failure occurs if you try
to deploy a message flow that contains a UDP that has had no value assigned to it.

At run time, after the UDP has been declared its value can be queried by subsequent
program statements but it cannot be modified.

Using UDPs, configuration data can be set easily and used just like normal
constants.

Java : To access broker user-defined properties from a JavaCompute node, use the
getUserDefinedAttribute(name) method, where name is the name of the property that
you are accessing.

"Message Flows", page 50 [58/1020].

CREATE COMPUTE MODULE DESTINOS_ERROR


DECLARE NomCuaPaperera EXTERNAL character ;
CREATE FUNCTION Main() RETURN BOOLEAN
BEGIN
SET OutputLocalEnvironment.Destination.MQ.DestinationData[I].queueName =
NomCuaPaperera ;
Shared Variables (within a EG)
Shared variables can be used to implement an in-memory cache in the message flow
(see Optimizing message flow response times). Shared variables have a long lifetime
and are visible to multiple messages passing through a flow (see Long-lived
variables). They exist for the lifetime of the execution group process, the
lifetime of the flow or node, or the lifetime of the node's SQL that declares the
variable, whichever is the shortest. They are initialized when the first message
passes through the flow or node after each broker startup.

The shared varables are visible to all instances of the flow within the Execution
Group
The logical message tree
A logical message tree is a structure that is created by one or more parsers when
an input message bit stream is received by a message flow.

url

How the message tree is populated


The message tree is initially populated by the input node of the message flow.

url or messagebroker_Message_Flows.pdf, page 251 [261 of 556]

Correlation names
A correlation name is a field reference that identifies a well-defined starting
point in the logical message tree and is used in field references to describe a
standard part of the tree format.

When you access data in any of the four trees (message, environment, local
environment, or exception list), the correlation names that you can use depend on
the node for which you create ESQL or mappings, and whether the node creates an
output message. For example, a Trace node does not alter the content of the message
as it passes through the node, but a Compute node can construct a new output
message.

You can introduce new correlation names with SELECT expressions, quantified
predicates, and FOR statements. You can create non-correlation names in a node by
using reference variables.

url

BLOB domain, manipulating messages in the


You cannot manipulate the contents of a BLOB message, because it has no predefined
structure. However, you can refer to its contents using its known position within
the bit stream, and process the message with a minimum of knowledge about its
contents.

The BLOB message body parser does not create a tree structure in the same way that
other message body parsers do. It has a root element BLOB, that has a child
element, also called BLOB, that contains the data.

You can refer to message content using substrings if you know the location of a
particular piece of information within the BLOB data. For example, the following
expression identifies the tenth byte of the message body:

InputBody.BLOB.BLOB[10]
url

You need to refer to the BLOB data as 'Root.BLOB.BLOB' or you could use
'Body.BLOB'.

url

Emir : Si pones 'XML' en el Domain, el mensaje deja de ser BLOB. El Filter node
deberia usar Root.XMLNSC.xxx

Mezcla : Si usas BLOB, y despues del filtro necesitas ver el mensaje como XML, usa
un "Reset Contents Descriptor" node (despues del filter node), que pone XML en el
Domain y tiene un TICK en "Reset Domain".

Amunt! Top Amunt!


RCD = Reset Content Descriptor
A Reset Content Descriptor (RCD) node has been inserted after the Catch node. This
prevents an exception being thrown by the Trace node in the case where a message
stored by a TimeoutControl node cannot be parsed by the TimeoutNotification node
and wouldn't be able to be parsed by the Trace node either. The RCD node resets the
domain to BLOB.

Schutz

Amunt! Top Amunt!


Trace node
Select Destination as File.
Set File Path to "e:\toolkit_trace\mb_trc.txt"
Set Pattern to

${Root} - llarg i detallat


${Body} - nomes texte
${ExceptionList} - to determine error cause with precision
${LocalEnvironment} - trace (MQ and MB) data in the LocalEnvironment tree
${Environment} - trace any (user) data in the Environment tree
${CURRENT_TIMESTAMP} - trace actual time
${DestinationList} - .
My selection is :

=== inici === ${CURRENT_TIMESTAMP}


${Root}
=== final === ${CURRENT_TIMESTAMP}
A more complete one :

#### Start Trace Input Message


Time: ${CURRENT_TIMESTAMP}
Broker: ${BrokerName} Version: ${BrokerVersion} Platform: ${Family}
ProcessID: ${ProcessId} BrokerUserId: ${BrokerUserId}
ExecutionGroupLabel: ${ExecutionGroupLabel}
# Transaction: ${Transaction}
Root Tree: ${Root}
Local envir (MQiMB, LocalEnvironment.File message tree) : ${LocalEnvironment}
User Envir : ${Environment}
#### End Trace Input Message
Body sample :

(
(0x03000000):UnknownParserName = 'MQSTR'
(0x03000000):BLOB = X'706f6e676f2033'
)
url

Testing and debugging message flow applications url or Message Flows, page 489
[499/556]

It Trace Node has "User Trace" selected, then you have to process the usertrace
using mqsireadlog and mqsiformatlog commands to get the UserTrace information.

How to have Tracing at Development but not at Production


Without having two flows, obviously.

Possible values for Fields :

Destination : "None", "User Trace", "File", "Local Error log".


File Path : "c:\tmp\mb\traza.txt"
Pattern :
Message Catalog :
Message Number : 3051.
Those values end up in file cyclon.cmf.

Three ways :

<null> File Path for the Trace Node properties.


promote property
Right-click on the Trace node and select "Promote Property". Drag-and-Drop
"Destination". It will appear it the flow properties from now on. Right-click on
any part of the white space and open Properties to modify it.
url

Use a filter before the trace which checks the broker name. If the name is the same
as your production broker, dont invoke the tracenode. If it isn't, go trough the
node and then the same path.
Here's an idea : no user trace nodes ; enable/disable trace
Have no trace nodes in the flow and use mqsichangetrace at runtime to trace the
flow. I've never had to use trace nodes in a flow to determine what it is doing. I
simply have a batch file (startTrace) to enable a trace and another (stopTrace) to
stop the tracing. Then I read the trace, everything you want to know is there.

Start :

rem %1 Broker
rem %2 EG
mqsichangetrace %1 -u -e %2 -r
mqsichangetrace %1 -u -e %2 -l debug -c 5000
Stop:

rem %1 Broker
rem %2 EG
mqsichangetrace %1 -u -e %2 -l none -c 5000
mqsireadlog %1 -e %2 -o readlog.out -u -f
mqsiformatlog -i readlog.out -o readlog.txt
start notepad readlog.txt
You can fine tune the script to trace just a flow as opposed to every flow in the
EG but you get the idea.

Amunt! Top Amunt!


Tracing a flow
@echo off
rem -----------------------------------------------------------------------
rem - Program: Usertrace Utility
rem - Version: 1.00
rem - Updated: 05/24/2000
rem - Purpose: start usertrace for a special messageflow (refresh the log)
rem - then wait (user can test the messageflow in another window)
rem - then dump the MQSI log to a file and use Notepad to view the
results
rem - at last usertrace is turned off again
rem - Required params : BrokerName, ExecutionGroup and MsgFlow - CASE SENSITIVE !
rem -----------------------------------------------------------------------

echo ------------------------------------------------------------------------
echo -- Usertrace Utility process started
IF "%2" == "" goto BADPARAM
IF "%3" == "" goto BADPARAM

:PROCESS
echo -- Executing command: mqsichangetrace %1 -u -e %2 -f %3 -l normal -r
mqsichangetrace %1 -u -e %2 -f %3 -l normal -r
echo -- Now test your Messageflow
pause
echo -- Executing command: mqsichangetrace %1 -u -e %2 -f %3 -l none
mqsichangetrace %1 -u -e %2 -f %3 -l none
echo -- Executing command: mqsireadlog %1 -u -e %2 -o %3.xml
mqsireadlog %1 -u -e %2 -o %3.xml
rem ------------------------------------------------------------------------
rem -- If the target file exists and REPLACE has not been specified then
rem -- do not overwrite the file. Report the error and end the process.
rem ------------------------------------------------------------------------
IF NOT EXIST %3.xml goto NOFILE
IF NOT EXIST %3.txt goto OK
IF "%4" == "REPLACE" goto REPLACEOK
IF "%4" == "replace" goto REPLACEOK
:NOREPLACE
echo -- ERROR !!!
echo -- Output file %3.txt exists. (REPLACE option not specified)
echo -- Specify replace option or delete the output file and try again.
goto SYNTAX

:REPLACEOK
del %3.txt
echo -- Output file %3.txt deleted (REPLACE option specified)

:OK
echo -- Executing command: mqsiformatlog -i %3.xml -o %3.txt
mqsiformatlog -i %3.xml -o %3.txt
del %2.xml
rem ------------------------------------------------------------------------
rem -- Make sure the output file exists before starting notepad
rem ------------------------------------------------------------------------
IF NOT EXIST %3.txt goto NOFILE
echo -- Output stored in file %3.txt
echo -- Starting the Notepad editor to view the file
echo -- Suggestion: Turn on word wrap in Notepad to easily view the output
start notepad %3.txt
goto FINISH

:NOFILE
echo -- ERROR !!!
echo -- The process did not produce any output. Look for error messages.
echo -- from previous commands. Check parameters and try again.
goto SYNTAX

:BADPARAM
echo -- Purpose:
echo -- start usertrace for a special messageflow (refresh the log)
echo -- then wait (user can test the messageflow in another window)
echo -- then dump the MQSI log to a file and use Notepad to view the results
echo -- at last usertrace is turned off again
:SYNTAX
echo ------------------------------------------------------------------------
echo -- Syntax: usertrace [BrokerName] [Execution Group] [Message Flow] [replace]
echo -- Remember, parameters are case sensitive!!!
echo ------------------------------------------------------------------------

:FINISH
echo -- Usertrace Utility process finished
echo ------------------------------------------------------------------------

:END

mqsichangetrace
[wbrkadm@dmqb261]:/home/wbrkadm> mqsichangetrace
BIP8104W: Changes a component's trace options.

Syntax (1):
mqsichangetrace componentName [-u | -t] -e egName [-f messageFlow] [-l level] [-m
mode] [-c size] [-r]

Syntax (2):
mqsichangetrace componentName -t -b [-l level] [-m mode] [-c size]
Command Options:
'componentName' Name of the component whose trace options are to be changed
'-u' indicates user trace (may only be used with '-e')
'-t' indicates service trace.
'-b' denotes tracing of a component other than an execution group
-b httplistener
valid values ?
agent
httplistener
'-e egName' Name of the execution group
'-f messageFlow' Name of the message flow
'-l level' specifies the trace level, 'none', 'normal' or 'debug'
'-m mode' specifies the trace mode, 'safe' or 'fast'
'-c size' specifies the trace file size in kilobytes [always 10240]
'-r' specifies that the log should be reset.

Exemple :
mqsichagetrace -u -e ExecutionGroupName -l debug -c 10240 -r
mqsireadlog
[wbrkadm@rcmqb272]:/home/wbrkadm> mqsireadlog
BIP8114W: Retrieves the trace log.

Syntax (1):
mqsireadlog componentName (-u | -t) -e executionGroupName [-f] [-o outputFileName]

Syntax (2):
mqsireadlog componentName -t -b subcomponent -f [-o outputFileName]

Command Options:
'-u' indicates user trace (may only be used with '-e')
'-t' indicates service trace
'-b subcomponent' name of the command or subcomponent (for example,
'agent')
'-e executionGroupName' name of the execution group
'-f' specifies that the log file is to be read directly from
the file system (mandatory for service trace)
'-o outputFileName' file name to write the trace log.
Display actual trace
mqsireporttrace WBRK_BROKER -u -e test
where
WBRK_BROKER = broker name
test = execution group name
Starting user trace
mqsichangetrace WBRK_BROKER -u -e test -l normal
Change user trace to debug
mqsichangetrace WBRK_BROKER -u -e test -l debug
Stopping user trace
mqsichangetrace WBRK_BROKER -u -e test -l none
Retrieving user trace
mqsireadlog WBRK_BROKER -u -e test -o trace.xml
Formatting trace
mqsiformatlog -i trace.xml -o formattrace.log
Tracing for all the components of MB
This is the com.ibm.etools.mft.util plug-in.

Configuration Manager proxy trace


If you select Errors to file, the default file to which trace is written is
install_dir\eclipse\workspace\cmptraceerror.log
Broker Administration trace settings
The default is None.
If you select Stored in a file, the default file to which trace is written is
install_dir/eclipse/workspace/.metadata/.plugins/com.ibm.etools.mft.admin/mbda.log

ODBC trace
Troubleshooting, pages 116-127 [124-135/188]

Nice command (from "db2cmd") : DB2 LIST SYSTEM ODBC DATA SOURCES

Muestra la lista de bases de datos registradas con ODBC.

Amunt! Top Amunt!


Filter node (ESQL)
ESQL Reference v 6.0 v 6.1

Writing ESQL

The message body is always the last child of root, and is identified by its parser
name, for example XML or MRM.

If you are referring to the input message to interrogate its contents in a Database
or Filter node, use correlation name Body to refer to the start of the message.
Body is equivalent to Root followed by the parser name, for example, Root.XML,
which you can use if you prefer.

Broker properties {from InfoCenter} that are accessible from ESQL and Java {mqJeff}
:
The only broker-defined properties that can be used in a Trace node are those in
the "General broker properties" group. See trace node

Amunt! Top Amunt!


Compute node (ESQL)
CREATE COMPUTE MODULE GirayDesvia_Compute
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
CALL CopyMessageHeaders();
-- CALL CopyEntireMessage();

set OutputRoot.XMLNSC.msg.a = InputRoot.XML.msg.b ;


set OutputRoot.XMLNSC.msg.b = InputRoot.XML.msg.a ;

set OutputRoot.XMLNSC.msg.c = '33333' ;

RETURN TRUE;
END;
END MODULE;
El Compute Node tiene varias salidas :

Out (de salida)


Out1
Out2
Out3 - the third alternate output terminal to which the transformed message might
be routed by a PROPAGATE statement.
Out4
Compute Node : Message Flows, page 492, [500/1020].

if ( Environment.AKI.CuaDeEntrada IS NOT NULL ) then


if ( Environment.AKI.CuaDeEntrada = 'MQ01.J2EE.TO.HUB.LOCAL' ) then
PROPAGATE TO TERMINAL 'out1' ;
else
if ( Environment.AKI.CuaDeEntrada = 'MQ01.J2EE01.TO.HUB.LOCAL' ) then
PROPAGATE TO TERMINAL 'out2' ;
else
PROPAGATE TO TERMINAL 'out3' ;
end if ;
end if ;
end if ;

En el "Out" i en el "Catch" del node MQinput s'ha fet


SET Environment.AKI.CuaDeEntrada = InputRoot.MQMD.SourceQueue ;
For example, if you want to create three copies of the input message received by
the Compute node, and send one to the standard "Out" terminal of the Compute node,
one to the first alternate "out1" terminal of the Compute node, and one to the
Label node "ThirdCopy", code the following ESQL:

SET OutputRoot = InputRoot;


PROPAGATE;
SET OutputRoot = InputRoot;
PROPAGATE TO TERMINAL 'out1';
SET OutputRoot = InputRoot;
PROPAGATE TO LABEL 'ThirdCopy';
In the above example, the content of OutputRoot is reset before each PROPAGATE,
because by default the node clears the output message buffer and reclaims the
memory when the PROPAGATE statement completes. 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;
PROPAGATE TO TERMINAL 'out1' DELETE NONE;
PROPAGATE TO LABEL 'ThirdCopy';
url

Also, to generate three copies of the input message, and not perform any further
action, include this code immediately before the RETURN TRUE statement:

SET OutputRoot = InputRoot;


PROPAGATE DELETE NONE;
PROPAGATE DELETE NONE;
Alternatively, you can modify the default behavior of the node by changing RETURN
TRUE to RETURN FALSE:

SET OutputRoot = InputRoot;


PROPAGATE DELETE NONE;
PROPAGATE DELETE NONE;
PROPAGATE;
RETURN FALSE;
url

Compute Node mode


Si queremos que el Mensaje ( OutputRoot ) se propague al nodo siguiente, debemos
seleccionar modo "Message".

Si queremos que el LocalEnvironment se propague al nodo siguiente, debemos


seleccionar modo "LocalEnvironment".
Valores posibles en "Compute Node properties -> Basic -> Compute Mode":

Message
LocalEnvironment
LocalEnvironment and Message
Exception
Exception and Message
Exception and LocalEnvironment
All
Expiry (ESQL)
Per fer que un missatge no expiri mai, hi posarem :

SET OutputRoot.MQMD.Expiry = MQEI_UNLIMITED ;


FileOut filename using Timestamp (ESQL)
Per fer que el fitxer de sortida de un node FileOutput porti un TimeStamp com la
part final del nom del fitxer, posarem aquest ESQL:

CREATE FUNCTION Main() RETURNS BOOLEAN


BEGIN

SET OutputRoot = InputRoot ; /* copy entire message */

DECLARE now CHARACTER;


SET now = CAST(CURRENT_TIMESTAMP AS CHARACTER FORMAT 'yyyyMMdd-HHmmssSSS');

SET OutputLocalEnvironment.Wildcard.WildcardMatch = now ;

RETURN TRUE;
END;
Amunt! Top Amunt!
Mapping node
Amunt! Top Amunt!
MQ Input node
The terminals of the MQInput node are:

Out - the output terminal to which the message is routed if it is successfully


retrieved from the WebSphere MQ queue.
Failure - the output terminal to which the message is routed if an error occurs.
Even if the Validation property is set, messages propagated to this terminal are
not validated.
Catch - the output terminal to which the message is routed if an exception is
thrown downstream and caught by this node.
Quina diferencia hi ha entre "an error occurs" i "an exception is thrown" ?

MQ Input node transactionality


Yes - means that the input node completes its own operation under sync point, and
the default behavior in the message flow is for actions to be taken under sync
point.
No - means that the input node completes its own operation out of sync point, and
the default behavior in the message flow is for actions to be taken out of sync
point.
Automatic - means that the node gets the message under sync point if the message is
persistent, and out of sync point if it is non-persistent.
Amunt! Top Amunt!
MQ Output node
The terminals of the MQOutput node are:

Out
The output terminal to which the message is routed if it has been successfully put
to the output queue.

Failure
The output terminal to which the message is routed if a failure is detected when
the message is put to the output queue.

Amunt! Top Amunt!


HttpInput node
The default port numbers for the embedded execution group listener are 7800 for
HTTP and 7843 for HTTPS.
You can change these port numbers, and port ranges used by the execution group
listeners, by using the mqsichangeproperties command.
To display actual values, use mqsireportproperties command :

mqsireportproperties IB9NODE -o HTTPConnector -e WSHOST -r

HTTPConnector
uuid='HTTPConnector'
userTraceLevel='none'
traceLevel='none'
userTraceFilter='none'
traceFilter='none'
port='7080'
address=''
maxPostSize=''
acceptCount=''
compressableMimeTypes=''
compression=''
connectionLinger=''
connectionTimeout=''
maxHttpHeaderSize=''
maxKeepAliveRequests=''
maxThreads=''
minSpareThreads=''
noCompressionUserAgents=''
restrictedUserAgents=''
socketBuffer=''
tcpNoDelay=''
explicitlySetPortNumber=''
enableLookups=''
enableMQListener=''
shutdownDelay=''
allowCrossConnectorPolling=''
autoRespondHTTPHEADRequests=''
Connector
port='7080'
type='Broker'
URLRegistration
url='/samplebrokerwshost'
UsedBySOAPNNodes='FALSE'
UsedByHTTPNNodes='TRUE'
nodeLabel='HTTP Input'

BIP8071I: El mandato ha finalizado correctamente.


The process biphttplistener.exe shall be listening there (use netstat plus
tasklist)

HttpRequest node
The HTTPRequest node determines the URL for the web service to which it sends a
request. Select one of the following three options; the node checks these in the
order shown (that is, the first always overrides the second, the second overrides
the third):

X-Original-HTTP-URL in the HTTPRequest header in the input message


LocalEnvironment.Destination.HTTP.RequestURL in the input message
The Web service URL property
Amunt! Top Amunt!
SOAP nodes
To trigger a web service, all we need is (in a Compute node preceeding a SOAP
Request):

set OutputRoot.SOAP.Body.q1:say_TOD.arg0 = 'my_param' ;


This is to generate
<soapenv:Body>

<q0:say_TOD>
<arg0>pepeta</arg0>
</q0:say_TOD>

</soapenv:Body>
</soapenv:Envelope>
Gateway mode - generic web service
SOAP Requets node has a Operation Mode checkbox.

invoke a specific web service defined by a WSDL interface


invoke a generic web service
Gateway mode allows you to configure your flow to handle generic SOAP
request/response and one-way messages, or to act as a facade between multiple web
services clients and multiple back-end web services providers. The node can onvoke
any binding operation.

Gateway opetarion mode for SOAP nodes :

declare q0 NAMESPACE 'http://wsServer.myfirst.com/' ;


SET OutputRoot.SOAP.Context.Namespace.(SOAP.NamespaceDecl)xmlns:soap12 = q0 ;
Here soap12 is the prefix used in the outbound message.

Use this ESQL to create the namespace prefix definition for ns1:

SET OutputRoot.SOAP.Context.Namespace.(SOAP.NamespaceDecl)xmlns:ns1 =
'http://a/b/c/myNamespace';
developerWorks

Changing the default URL for a SOAPRequest node or a SOAPAsyncRequest node request

CREATE PROCEDURE overrideDefaultSOAPRequestURL ( IN LocalEnvironment REFERENCE, IN


newUrl char ) BEGIN
/*******************************************************************************
* Change the URL to which the SOAPRequest or SOAPAsyncRequest node sends the
request.
*
* IN LocalEnvironment: the LocalEnvironment to be modified.
* IN newURL: the URL to which to send the request.
*
*******************************************************************************/
SET OutputLocalEnvironment.Destination.SOAP.Request.Transport.HTTP.WebServiceURL
= newUrl ;
END;
You can also override the Operation property :

SET OutputLocalEnvironment.Destination.SOAP.Request.Operation = 'myOperation' ;

What happens with NameSpace ?


My first webservice requires

declare q0 NAMESPACE 'http://wsServer.myfirst.com/' ;


And the second web service requires
declare q1 NAMESPACE 'http://tod.ws.com/' ;
DECLARE statement

Here is the answer, due to magnificent Nacho:

(a) classic way, using WSDL


(b) generic - requires 3 parameters
namespace
operation
url
CASE ws_num

WHEN '1' THEN -- <Mensaje> <Evento> EVENT/WS </Evento> <wsn> 1 </wsn>


</Mensaje>

declare q0 NAMESPACE 'http://wsServer.myfirst.com/' ;


SET OutputRoot.SOAP.Context.Namespace.(SOAP.NamespaceDecl)xmlns:q0 =
'http://wsServer.myfirst.com/' ;
SET
OutputLocalEnvironment.Destination.SOAP.Request.Transport.HTTP.WebServiceURL =
'http://localhost:8080/wsServer_hello' ;
SET OutputLocalEnvironment.Destination.SOAP.Request.Operation =
'getGreeting' ;
set OutputRoot.SOAP.Body.q0:getGreeting.arg0 = 'sebas using 1st web
service' ;

WHEN '2' THEN -- <Mensaje> <Evento> EVENT/WS </Evento> <wsn> 2 </wsn>


</Mensaje>

declare q1 CHARACTER ;
set q1 = 'http://tod.ws.com/' ; -- 1st param, namespace
declare operacion CHARACTER ;
set operacion = 'say_TOD' ; -- 2nd param, operation

SET OutputRoot.SOAP.Context.Namespace.(SOAP.NamespaceDecl)xmlns:q1 = q1
;
SET
OutputLocalEnvironment.Destination.SOAP.Request.Transport.HTTP.WebServiceURL =
'http://localhost:8181/TOD_server' ; -- 3rd param, url
SET OutputLocalEnvironment.Destination.SOAP.Request.Operation =
operacion ;

CREATE LASTCHILD OF OutputRoot.SOAP.Body NAMESPACE q1 NAME operacion ;


set OutputRoot.SOAP.Body.*.arg0 = 'sebas using 2nd web service' ;

else
Amunt! Top Amunt!
Java compute node
Required classes, as mongo-java-driver-2.4.jar, have to go into
c:\MQSI\9.0.0.0\classes !

Amunt! Top Amunt!


FileInput node
Use the FileInput node to process messages that are read from files. One or more
messages can be read from a single file, and each message is propagated as a
separate flow transaction. The part of a file that generates one message flow
transaction is called a record. A file can be a single record, or a series of
records. Properties on the node specify how the FileInput node determines the
records in a file. When the FileInput node propagates a message, it stores
information about it in the LocalEnvironment.File message tree. If the input file
is empty, an empty message is propagated (assuming that it is valid).

Its Basic properties are:

Input directory
File name or pattern
Your input file name will be in InputLocalEnvironment.File.Name. You could store in
environment to use it for your output files creation.
Action on successful processing
Move to Archive subdirectory (mqsiarchive)
Add Timestamp and Move to Archive subdirectory (mqsiarchive)
Delete
Replace duplicate archive files: Y/N
On the Input Message Parsing tab, set values for the properties that the node uses
to determine how to parse the incoming message.

Use the Records and Elements tab to specify how each file is interpreted as
records, as "Record detection := Whole File ; " - specifies that the whole file is
a single record

FileInput node + "Advanced" settings


En el nodo FILEINPUT de la versin 6.1 del broker, una de las propiedades del nodo
es la ruta del fichero de donde queremos leer los ficheros.
Es posible cargar este valor dinmicamente de las variables de sistema operativo de
alguna variable de entorno ? O cargarlo de alguna variable de un fichero properties
o similar?
Es importante porque las rutas en los distintos entornos (desarrollo, preproduccin
y produccin) son distintas.

Lo ms fcil es cambiar el atributo en el fichero BAR.


Tambin se puede usar LocalEnvironment:

LocalEnvironment.File
LocalEnvironment.WrittenDestination.File
LocalEnvironment.Wildcard.WildcardMatch
Para ms detalles, Help -> Search: ac55410

FileInput trace result


If we code:

FileInput
Trace
MQOutput
We get this trace:

+ + + BPA file input OK - busquem LocalEnvironment.File - 2013-02-18


23:25:48.052879
( ['MQROOT' : 0xda8838]
(0x01000000:Name):File = (
(0x03000000:NameValue):Directory = 'c:\temp\mb\filein' (CHARACTER)
(0x03000000:NameValue):Name = 'fitxer_copiat.txt' (CHARACTER)
(0x03000000:NameValue):LastModified = GMTTIMESTAMP '2013-02-18 22:25:17.062'
(GMTTIMESTAMP)
(0x03000000:NameValue):TimeStamp = '20130218_222548_031020' (CHARACTER)
(0x03000000:NameValue):Offset = 0 (INTEGER)
(0x03000000:NameValue):Record = 1 (INTEGER)
(0x03000000:NameValue):Delimiter = NULL
(0x03000000:NameValue):IsEmpty = FALSE (BOOLEAN)
)
(0x01000000:Name):Wildcard = (
(0x03000000:NameValue):WildcardMatch = 'fitxer_copiat.txt' (CHARACTER)
)
)
- - - Final
Amunt! Top Amunt!
FileOutput node
File Name : the name of the output directory and the names of the output files are
determined by the node properties that you specify and by elements of the message
that is being processed.

The file name to be used is determined as follows:

If the file name contains no wildcard, the value of this property is the name of
the file created.
If the file name contains a single wildcard, the value of the element
LocalEnvironment.Wildcard.WildcardMatch in the current message replaces the
wildcard character, and the resulting value is the name of the file created.
The output directory path to be used can be overridden by values in the current
message. The name of the file can be overridden by values in the current message.
See the information relating to the Request tab for details about how to do this,
using $LocalEnvironment/Destination/File/Directory and
$LocalEnvironment/Destination/File/Name

EOF : in tab "Records and Elements", set "Record definition := Record is Whole File
;"

(s) FTP
If the output is to a remote filesystem, accessed using SFTP, we have to specify a
"security identity" in the node properties (here "sftp_id"), that has been defined
using the mqsisetdbparms command. The user identifier and password that are to be
used to log on to the FTP or SFTP server are obtained from this definition, the
name of which must have the prefix ftp:: :

c:\> mqsisetdbparms broker_name -n sftp::sftp_id -u sftp_user -p sftp_pwd


Use ssh keys instead. First generate them for the broker id (using ssh-keygen) then
supply the broker id's public key (.ssh/id_rsa.pub) to the sftp server (to manually
add it to their .ssh/authorized_keys file as a one time task). Then set up the
setdbparms to reference the brokers private key file.
Code:

c:\> mqsisetdbparms MY_BK -n sftp::sec_id -u sec_user -i /home/MY_BK/.ssh/id_rsa


As if by magic - no passwords needed ever again.
Amunt! Top Amunt!
Timer nodes
MB timer nodes
Two built-in nodes:
TimeoutControl
TimeoutNotification
Note naming convention of adding UID (TIME) to node name. Since the purpose of the
TimeoutControl node is to dynamically set the characteristics of a
TimeoutNotification node, the UID of the TimeoutNotification node should be the
same as the UID of the controlling TimeoutControl node. Multiple TimeoutControl
nodes can control the same TimeoutNotification node by specifying the same UID.

TimeoutNotification node
The purpose of this node is to act as an alarm clock, initiating a message flow
when the timer goes off. The TimeoutNotification node would be the first node in a
timer-controlled message flow. It has no In terminal.

As a standalone node, TimeoutNotification nodes support simple, fixed interval


timer events. For example, you can have a message flow executed every 30 seconds,
every hour, or even every 17 years.

As always, wire the Catch terminal of the TimeoutNotification node so that you
avoid any unpleasant retry conditions.

The tree coming out of the node contains only a Properties and LocalEnvironment
subtree.

TimeoutControl node
The purpose of a TimeoutControl node is to let you set of the parameters of a
TimeoutNotification node.

Including one or more TimeoutControl nodes in either the same or a different


message flow (or even different execution groups) makes the patterns of generated
timer events much more flexible.

The TimeoutNotification node's Operation Mode properties must be changed from


Automatic to Controlled for the TimeoutControl node to have any effect.

developerWorks Schutz. See "Programming patterns"

The TimeoutNotification node in "Automatic" mode does not produce a message tree
suitable for sending to an MQOuput node (for example, there is no MQMD subtree).
The following ESQL code can be used to create an appropriate message (and would be
coded in the "BuildTimeoutMessage" node above).

CREATE FUNCTION Main() RETURNS BOOLEAN


BEGIN
CALL CopyMessageHeaders();
-- Capture the request as an output message
SET "OutputRoot"."Properties"."MessageDomain" = 'XML';
SET "OutputRoot"."MQMD"."Format" = MQFMT_STRING;
SET "OutputRoot"."XML"."TimeoutRequest" =
"InputLocalEnvironment"."TimeoutRequest";
RETURN TRUE;
END;
Amunt! Top Amunt!
Job execution node
IA9Z: WebSphere Message Broker - Job Execution Node : download, PDF

How about using a JCN with Runtime.exec() instead of the Job Execution Node?

Amunt! Top Amunt!


Email nodes
Debug using ExceptionList !

CALL CopyMessageHeaders();

-- Add recipient information to the EmailOutputHeader


SET OutputRoot.EmailOutputHeader.To = '<recipient email address>';
SET OutputRoot.EmailOutputHeader.Cc = '<recipient email address>';
SET OutputRoot.EmailOutputHeader.Bcc = '<recipient email address>';

-- Add sender information to EmailOutputHeader


SET OutputRoot.EmailOutputHeader.From = '<sender email address>';
SET OutputRoot.EmailOutputHeader."Reply-To" = '<reply email address>';

-- Add subject to EmailOutputHeader


SET OutputRoot.EmailOutputHeader.Subject = 'Replaced by ESQL compute
node.';

-- Add SMTP server information to the LocalEnvironment


SET OutputLocalEnvironment.Destination.Email.SMTPServer
='<smtp.server:port>';

-- Create a new message body, which will be sent as the main text of
the email.
SET OutputRoot.BLOB.BLOB = CAST( 'This is the new text for the body of
the email.' AS BLOB CCSID 1208 ) ;

RETURN TRUE;
END ;
tkt help

Amunt! Top Amunt!


IMS node
Allows message flows to cal IMS transactions and handle responses. Typical
scenarios include Web Service -> IMS, File -> IMS, SAP -> IMS. Complements MQ IMS
Bridge and IMS Web Services currently available.

info center

Amunt! Top Amunt!


A minimum sample : MQ Input + Trace + MQ Output
Create required objects using CMD files in "\\MQ\CMDS\T400\MB7"

Lets start with "New(Message Flow Project)" := 'ICS', with no referenced projects.
On the "ICS flow -> Flows", create a "New(Message Flow)" := 'first flow' ;

Place 3 nodes on the canvas :

a MQ input (ICS_IN) - select "Message Domain := XMLNSC" under "Input Message


Parsing" ;
a Trace node - destination := "file", path := "c:\temp\mb\mytrace.txt", pattern :=
${BODY}
and a MQ output (ICS_OUT), without destination queue manager
Join Trace-Out pin with MQ_Output-In and Trace-In pin to MQ_Input-Out

Identify the version by clicking on the canvas of the "msgflow" and filling the
"version" property at bottom. You can see this value in the message flow deployed
in the execution group, under the "Properties" tab.

Save it using "Ctrl+S".


To create the BAR file, right-click on the ICS project, and select "New(Message
Broker Archive)" := 'mybar.bar' ; On the right, select the "first_flow.msgflow"
resource and click "Build broker archive" at bottom.

To deploy the BAR file, right-click on the BAR file, and select "Deploy", and
select Execution Group "EG1".

If there is an error in the deployment, fix it, and then right click on BAR file,
and select "Build and Save BAR" to re-create the BAR file - icon disapears. Deploy
again.

If the deployment ends ok (and the Input Queue exists), there must be a thread
having opened the input queue for "input" - use MQ Explorer. And placing a message
in the intput queue shall trigger the writing into the trace file ; also, a message
is written into the output queue.

By example, this message goes fine thru the flow, and leaves this trace:

<mymsg><nom>Sebastia</nom></mymsg>

( ['xmlnsc' : 0x17808060]
(0x01000000:Folder):mymsg = (
(0x03000000:PCDataField):nom = 'Sebastia' (CHARACTER)
)
)
Amunt! Top Amunt!
A FileOutput sample, using Compute Node
We use these nodes :

MQInput - Input Message Parsing, Message Domain := BLOB ;


Compute - Compute Mode := All ;
Trace - ${LocalEnvironment}
FileOutput - Directory := "c:\temp\mb\fileout" ; File Name or Pattern := "fo*" ;
In Compute Node we code:

CREATE COMPUTE MODULE BPA_mf_Compute


CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
SET OutputRoot = InputRoot ; /* copy entire message */

DECLARE now CHARACTER;


SET now = CAST(CURRENT_TIMESTAMP AS CHARACTER FORMAT 'yyyyMMdd-HHmmssSSS');

SET OutputLocalEnvironment.Wildcard.WildcardMatch = now ;

RETURN TRUE;
END;
The result is a MQ message written into a file with timestamp in its name:

c:\temp\mb\fileout> dir
Directory of c:\temp\mb\fileout

17/02/2013 10:16 34 fo20130217-101634066


17/02/2013 10:16 34 fo20130217-101637611
17/02/2013 10:16 34 fo20130217-101638126
17/02/2013 10:16 34 fo20130217-101638792
17/02/2013 10:16 34 fo20130217-101639427
17/02/2013 10:17 34 fo20130217-101719668
17/02/2013 10:17 34 fo20130217-101720526
And this trace:

+ + + BPA input OK - busquem LocalEnvironment.Wildcard.WildcardMatch - 2013-02-17


10:17:20.526866
( ['MQROOT' : 0x17809218]
(0x01000000:Name):Wildcard = (
(0x03000000:NameValue):WildcardMatch = '20130217-101720526' (CHARACTER)
)
)
- - - Final
Amunt! Top Amunt!
A complete sample : Filter + Compute ESQL
The MQ_Input node had defined Message Domain := "XML" ;

El missatge de entrada era :

Dades de entrada, gas_in : <mimsg><a>Sebas</a><b>Alte</b></mimsg>


El filtre i la transformaci foren :

CREATE FILTER MODULE cyclon_Filter

CREATE FUNCTION Main() RETURNS BOOLEAN


BEGIN

DECLARE MSG_SRC CHAR ;


SET MSG_SRC = substring(Root.XMLNSC.mimsg.a FROM 2 FOR 1) ; // Sebas

IF ( MSG_SRC = 'e' ) THEN RETURN TRUE ;


END IF ;

RETURN FALSE ;

END;

END MODULE;

CREATE COMPUTE MODULE cyclon_Compute


CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN

CALL CopyMessageHeaders();

set OutputRoot.XMLNSC.mimsg.a = InputRoot.XML.mimsg.b ; // aqui es fa


set OutputRoot.XMLNSC.mimsg.b = InputRoot.XML.mimsg.a ; // el
"encreuament" !
set OutputRoot.XMLNSC.mimsg.c = '33333' ;

RETURN TRUE;
END;

CREATE PROCEDURE CopyMessageHeaders() BEGIN


DECLARE I INTEGER;
DECLARE J INTEGER;
SET I = 1;
SET J = CARDINALITY(InputRoot.*[]);
WHILE I < J DO
SET OutputRoot.*[I] = InputRoot.*[I];
SET I = I + 1;
END WHILE;
END;

CREATE PROCEDURE CopyEntireMessage() BEGIN


SET OutputRoot = InputRoot;
END;

END MODULE;
Els resultats obtinguts son :

Dades de sortida, gas_out_true :


<mimsg><a>Alte</a><b>Sebas</b><c>33333</c></mimsg>
Another sample
Input: mensaje XML. Por ejemplo:

<msg><a>7777</a></msg>
Compute node:

CALL CopyEntireMessage();

declare ENYE char cast(X'A5' as char CCSID 437); -- enye mayuscula


declare CRLF char cast(X'0A0D' as char CCSID 437);

set OutputRoot.XMLNSC.msg.chars = 'VIVA' || CRLF || 'ESPA' || ENYE ||


'A';

RETURN TRUE;
Output (en caracter):

<msg>
<a>7777</a>
<chars>VIVA..ESPAA</chars>
</msg>
Output (en hexadecimal):

00000000 <msg><a> 7777</a> 3C6D7367 3E3C613E 37373737 3C2F613E


00000016 <chars>V IVA..ESP 3C636861 72733E56 4956410A 0D455350
00000032 AA</cha rs></msg 41D1413C 2F636861 72733E3C 2F6D7367
00000048 > 3E
Notars que se convirti la ee de codepage 437 (ASCII) a 1252 (Unicode).

SAG sample
Tengo un flujo con un nodo MQ-IN, un nodo "COMPUTE" en medio y un nodo MQ-OUT a la
salida.

Con un mensaje de entrada como

<msg><a>a</a><b>bb</b></msg>
Con un "compute node" con este codigo, obtenemos estos mensajes de salida

CREATE COMPUTE MODULE cnt_flow_Compute


CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
CALL CopyEntireMessage();
set OutputRoot.XMLNSC.cap = '33333'; --
<msg><a>a</a><b>bb</b></msg><cap>33333</cap>
set OutputRoot.XMLNSC.msg.cap = '33333'; --
<msg><a>a</a><b>bb</b><cap>33333</cap></msg>

RETURN TRUE;
END;
Amunt! Top Amunt!
SHARED var
Shared variables (defined with the SHARED keyword) can be used to implement an in-
memory cache in the message flow; see Optimizing message flow response times.
Shared variables have a long lifetime and are visible to multiple messages that
pass through the flow; see Long-lived variables. They exist for the lifetime of the
integration server process, the lifetime of the flow or node, or the lifetime of
the node's SQL that declares the variable (whichever is the shortest). They are
initialized when the first message passes through the flow or node after each
broker startup.

See also the ATOMIC option of the BEGIN ... END statement. The BEGIN ATOMIC
construct is useful when a number of changes have to be made to a shared variable
and when it is important to prevent other instances seeing the intermediate states
of the data.

SHARED sample
{pend} I want to have a flow that receives messages and inserts a sequence number
in each one of them, keeping the value as a global variable in cache. {sag,
20131030}

DECLARE sebas SHARED Integer 17 ;


DECLARE Initialized SHARED BOOLEAN FALSE ;

-- input msg

CREATE COMPUTE MODULE cache_flow_Compute

CREATE FUNCTION Main() RETURNS BOOLEAN


BEGIN

IF NOT Initialized THEN


BEGIN ATOMIC
SET Initialized = TRUE ;
SET sebas = 17 ;
end;
END IF ;

BEGIN ATOMIC
set sebas = sebas + 1 ;
END ;

CALL CopyEntireMessage() ;
set OutputRoot.XMLNSC.cap = sebas ; --
set OutputRoot.XMLNSC.cul = cast(sebas as character) ; -- Output

RETURN TRUE;
END;

CREATE PROCEDURE CopyEntireMessage() BEGIN


SET OutputRoot = InputRoot ;
END;

END MODULE;
Amunt! Top Amunt!
Global cache
"Global Cache allows a number of Brokers to be integrated for workload balancing.
Global Cache provides the ability to have a cache storing information about the
requester which would later be used to correlate the replies correctly. Using
Global cache gives the flexibility for different brokers to handle the request and
reply parts of an application. Using a global cache allows you to scale up the
number of clients, while maintaining predictable response time for each client."

Accs a BBDD des ESQL


SET Environment.IMI.Query[] =
( SELECT

D1.ID_ENT AS EntornoDst,
D1.QUEUE_DST_DFT AS ColaSalidaDft,
D1.QUEUE_DST_PET AS ColaSalidaPet,
D1.PATH_MOD_SVR AS PathModSvr,
D1.TIPO_MOD_SVR AS TipoSvr,
D1.NOMBRE_CLASE AS Nom_Clase,
D1.NOMBRE_METODO AS Nom_Metode

FROM Database.BROKER.TBL_DST_LIST AS D1 WHERE D1.ID_SERVEI = SRV_TMP ) ;


DB2 access from MB tkt easy sample
start DB2 CLP
create savings database : "db2 create database SAVG_ACC"
create the table and procedure in the savings database: "db2 -vf
setupSavingsAccount.sql"
create loan database: "db2 create database LOAN_ACC"
create the table and procedure in the loan database: "db2 -vf setupLoanAccount.sql"
create queue manager: "crtmqm QM"
start queue manager: "strmqm QM"
create queue manager objects: "runmqsc QM < queues.defs"
start MBCL
create broker: "mqsicreatebroker BROKER -i myuser -a mypwd -q QM"
start the broker: "mqsistart BROKER"
start toolkit
import project interchange "DebitCredit.zip" file
create execution group "DebitCredit"
open DebitCreditFlow_deploy.mbtest, click "Send message", select execution group
"DebitCredit" and click "Finish".
open DebitCreditFlow_test.mbtest, select Enqueue and then click "Send message";
select Dequeue and then click "Get message".
accessing DB2 from WebSphere Message Broker using stored procedures
{\\MB\ToolKit\DB2}

Amunt! Top Amunt!


THROW
The THROW esql statement generates a user exception. It produces a rollback to the
MQInput node, where the Catch pin will be used.

IF ( Environment.NumDestinos = 0 ) THEN
THROW USER EXCEPTION MESSAGE 2950
VALUES ( 'Not found Service Code (' || InputRoot.MQRFH2.usr.COD_SERVEI || ')
in table "DESTINOS_APLICACION".' ) ;
ELSE
MESSAGE is an optional clause; if you omit it, it defaults to the first message
number of the block of messages provided for using THROW statements in WebSphere
Message Broker catalog (2951). If you enter a message number in the THROW
statement, you can use message numbers 2951 to 2999.
ESQL, MB version 6, page 252

Si usas el pin "CATCH" deberas tener el Environment intacto. Es en "FAILURE" donde


recibes un Environment "nuevo".
Es muy comn poner cosas en el Environment antes de un THROW, para pasarle datos al
CATCH. Por ejemplo:

SET OutputRoot.MRM = inv;


Set Environment.inv = inv;
PROPAGATE;
Amunt! Top Amunt!
User node
Permite cdigo C (o Java) escrito por el usuario.

Se despliega en un fichero ".LIL" en el broker.

Amunt! Top Amunt!


UOW - unit of work
A transaction describes a set of updates that are made by an application program,
which must be managed together.

Configuring global coordination of transactions (two-phase commit)


Configuring transactionality for message flows

You can configure the nodes in your message flow to determine how the work taken by
each node participates in the message flow transaction. Most nodes for which
transactionality is relevant have one or more properties that you can configure to
dictate behavior. Therefore, you can decide for each individual node whether it
participates in the message flow transaction, or operates independently. Typically,
these properties include an option of Automatic, so that subsequent nodes in the
flow assume the characteristics set by the input node.

Commit or rollback
If the resource can participate in a transaction, you can configure it so that the
work it does is committed or rolled back only when the message flow completes, or
when the node completes. Databases and WebSphere MQ queues are examples of
resources that you can use in this way. If the resource does not have transactional
behavior, all the work that it does is committed immediately. For example, files
and HTTP connections do not support transactions.

Updates that are made by a message flow are committed when the flow processes the
input message successfully. The updates are rolled back if both of the following
conditions are met:

a node in the flow throws an exception that is not caught by a node other than the
input node (for example, the node itself, or a TryCatch node)
the Catch terminal of the input node is not connected
Read message flow transactions to understand how the broker handles transactions

run this sample : error handling


Start here :

setup DB, DB2 or Oracle


import the sample and create the queues
set up the sample - Important item: configuring ODBC connections for globally
coordinated transactions, as DB2
run the sample
SAG's sample
No em funciona un fluxe que escriu en 2 nodes de sortida. Si el segon node esta ple
i no te "Failure" cablejat, el missatge sempre va a "Catch" del node de entrada,
sense importar si es transaccional o no.

Amunt! Top Amunt!


web service using patterns
Open toolkit and select "start from patterns" in Quick Start wizards list. Select
"Service Enablement" on left and then MQ request-response.

The solution is to implement a message flow that provides a service entry point.
When a service request is received, the reply identifier is stored on an internal
queue and the request is forwarded to the provider application. When the response
is received from the provider application, the reply identifier is recovered and a
web services reply, which contains the provider response, is returned to the
requesting application.

Amunt! Top Amunt!


State-less flows
If we place a MB flow between App_Origin and App_Server, and the reply message has
to be also modified by MB, it is very usual to use a temporary queue in the flow to
keep the original Reply-To parameters until the reply message comes

.----------. .-------------------------------.
.----------.
| | (1) | | (2)
| |
| App | --------> Q1 | ... MB flow ... | Q2 -------->
| App |
| Origin | | |
| Server |
| | Q4 | msgID=nnn RQ=Q4 | Q3
| |
| | | |
| |
.----------. .-------------------------------.
.----------.

msg (1) has ReplyToQ = Q4


msg (2) has ReplyToQ = Q3
If we want to be state-less, so reply can use another (identical) flow, then the
state (msg in tmp q) must go in the message header, guess RFH2.

No - If you're using v7 you shouldn't be using an MQRFH2 but message properties


If working with V7 you can set the message properties and have the system transform
them into an RFH2. See the property control parameter on the queue / channel.

SET OutputRoot.MQRFH2.usr..ReplyIdentifier =
InputLocalEnvironment.Destination.SOAP.Reply.ReplyIdentifier ;
How to place user-data in "message properties" ?
An 18 minute Powerpoint presentation about message properties, including how it
relates to RFH2 headers: url

Amunt! Top Amunt!


Debug
First, let's set flow debug preferences.

Window + Preferences - start Preferences wizard


select Flow Debug - opens the Flow Debugger preferences page
make own selections
Use the "Flow Debug" perspective for debugging. In its default mode, this
perspective shows 4 windows :

Flow Debug view


Flow Breakpoints view (shared pane)
Flow Debug Message view (shared pane)
Message Flow editor
Before you can debug a message flow, you must attach the flow debugger to the flow
engine (execution group) where your flow is deployed.

switch to the Flow Debug perspective (escarbat vermell que mira cap a la dreta del
menu lateral esquerre)
click the Attach to Flow Runtime icon on the Toolbar (escarbat vermell a dalt)
in the Hosts list box, select the host computer that the flow engine is running on.
in the listbox, select select the flow engine containing the flow you want to
debug.
in the Flow Debug view, double-click the message flow you want to debug.
in the Message Flow editor, add a breakpoint to a connection that leads out of the
input node. The breakpoint appears.
when the next message comes into the flow and arrives at the breakpoint, the flow
pauses and the breakpoint icon changes.
Message Flows, page 490 - url

The Message Flow editor has different functions in different perspectives:

In the Broker Application Development perspective, the Message Flow editor is used
to create, graphically display, and edit flows.
In the Flow Debug perspective, the Message Flow editor is used only to graphically
display and debug flows, as described in this topic.
Tip: From a single workbench, the debugger can attach to more than one execution
group, and debug multiple flows in different execution groups (and therefore
multiple messages) at the same time. However, a deployed flow in one execution
group can be debugged by only one user at a time, so if you attach your debugger to
it, another user cannot also attach a debugger at the same time.
Resum How to Debug
Hacer deploy como siempre.
Ir a la "Debug Perspective"
Right-click "Attach"
Select the host where the broker runs, click Next.
Select the Execution group, click Finish.
You're ready to debug.

Right-click on a node to set breakpoints.


Put a message to run the flow
Important workspace setting :
Solapa superior, segunda por la derecha, "Ventana" + "Preferencias" + "Flow
Debug" :
Debug Message Broker CSD 3 and beyond

Gracias, Lourdes !

Do Debug
install RAC ( without security )
start RAC at Port 10002 (RAService.exe @ Guindows)
add Breakpoint(s)
open perspective Debug
"New Configuration" :
escollir Flow Project
escollir Host
escollir Flow Engine
send messages and debug flow
Right-click on New Configuration + Terminate & Remove
Gracias, Mario !

Amunt! Top Amunt!


MQ Input Exception - how to display
If we connect the "Exception" pin of the MQ Input node directly to a MQ Output node
and there is an Exception in the flow, we shall find a message like this one in the
queue :

<ExceptionList>
<RecoverableException>
<File>F:\build\S610_P\src\DataFlowEngine\ImbTraceNode.cpp</File>
<Line>334</Line>
<Function>ImbTraceNode::evaluate</Function>
<Type>ComIbmTraceNode</Type>
<Name>LAB9#FCMComposite_1_3</Name>
<Label>LAB9.Trace</Label>
<Catalog>BIPv610</Catalog>
<Severity>3</Severity>
<Number>2230</Number>
<Text>Caught exception and rethrowing</Text>
<ParserException>

<File>F:\build\S610_P\src\MTI\MTIforBroker\GenXmlParser4\ImbXMLNSCParser.cpp</File>

<Line>828</Line>
<Function>ImbXMLNSCParser::parseFirstChild</Function>
<Catalog>BIPv610</Catalog>
<Severity>3</Severity>
<Number>5009</Number>
<Text>XML Parsing Errors have occurred</Text>
<ParserException>

<File>F:\build\S610_P\src\MTI\MTIforBroker\GenXmlParser4\ImbXMLNSCDocHandler.cpp</F
ile>
<Line>507</Line>
<Function>ImbXMLNSCDocHandler::handleParseErrors</Function>
<Type>ComIbmMQInputNode</Type>
<Name>LAB9#FCMComposite_1_1</Name>
<Label>LAB9.MQInput LAB9_IN XMLNSC</Label>
<Catalog>BIPv610</Catalog>
<Severity>3</Severity>
<Number>5004</Number>
<Text>An XML parsing error has occurred while parsing the XML document</Text>
<Insert> <Type>2</Type> <Text>1504</Text> </Insert>
<Insert> <Type>2</Type> <Text>2</Text> </Insert>
</ParserException>
</ParserException>
</RecoverableException>
</ExceptionList>
Amunt! Top Amunt!
Deploy and MQ
The Deploy operation results in a message being put to MQ queue
SYSTEM.BROKER.ADMIN.QUEUE, which is then processed by the Broker.
The Broker should then put a message to MQ queue SYSTEM.BROKER.ADMIN.REPLY.
Qui hi ha escoltant:
display qstatus(SYSTEM.BROKER.ADMIN.QUEUE) type(handle) all
5 : display qstatus(SYSTEM.BROKER.ADMIN.QUEUE) type(handle) all
AMQ8450: Display queue status details.
QUEUE(SYSTEM.BROKER.ADMIN.QUEUE) TYPE(HANDLE)
APPLDESC( )
APPLTAG(:\MQSI\7.0\bin\bipbroker.exe)
APPLTYPE(USER) BROWSE(NO)
CHANNEL( ) CONNAME( )
ASTATE(NONE) HSTATE(ACTIVE)
INPUT(SHARED) INQUIRE(NO)
OUTPUT(NO) PID(3352)
QMURID(0.941) SET(NO)
TID(1)
URID(XA_FORMATID[00000000] XA_GTRID[] XA_BQUAL[])
URTYPE(QMGR) USERID(mbadmin@TTLCBA27)
Problemes :

msgflow is not configured to be published


file korreu.esql can not be added to archive as it is undeployable
Amunt! Top Amunt!
RAC
Rational Agent Controller (RAC) supports message flow debugging. If you want to use
the Debugger, you must install RAC on each system on which you start a broker that
hosts message flows. The RAC component that you install on the broker is a server
that communicates with the RAC client which is embedded in the Message Brokers
Toolkit.

V 6 Installation Guide, page 19 [37/176]

RAC is not required after MQ v 6.1 [javier]

Amunt! Top Amunt!


RAD
Pre-requisites. Before you can publish (deploy) a configuration using rapid
application development (RAD) you need to :

create a Configuration Manager


the MQ listener must be running
create a domain
add a broker to that domain
create an execution group within that broker
Amunt! Top Amunt!
Let's start running ...
the installation samples
korreus
praktikes Lourdes
ping responder
Run the samples
First, we have to configure the product, this is, we need to create a broker
domain, that represents the broker runtime environment. A broker domain contains a
single Configuration Manager with associated brokers. It may also contain a User
Name Server if authentication is used for publish/subscribe messaging.

To quickly create a default configuration, run the Getting Started Wizard :


Start -> Programs -> WebSphere Studio -> MB Toolkit

The queues to use will be :

PAGER
SURFWATCH
SURFWATCH_FAIL
TEXTMESSENGER
TEXTMESSENGER_FAIL
Ping responder
Input message

<Ping>
<Text>Hello There</Text>
</Ping>
Output message

<PingResponse>
<Text>Hello There</Text>
<ReceivedTime>current timestamp</ReceivedTime>
</PingResponse>
ESQL

CREATE COMPUTE MODULE PingResponder_Compute


CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
CALL CopyMessageHeaders();
-- CALL CopyEntireMessage();
-- Create new response body
SET OutputRoot.XMLNSC.PingResponse.Text = InputRoot.XML.Ping.Text;
SET OutputRoot.XMLNSC.PingResponse.ReceivedTime = CURRENT_TIMESTAMP;
RETURN TRUE;
END;
"Getting started with WBI MB" Redbook, 2004, page 28 de 74. "Getting started with
the Broker Exercises" RedBook, page 27 of 386.

Amunt! Top Amunt!


v7 samples
MB v7 samples in publib. MB samples in "Toolkit samples" in on-line documentation
v7 : import, deploy, run.

You can run samples only when you use the information center that is integrated
with the WebSphere Message Broker Toolkit : Help -> Samples and Tutorials ->
Product = MB tkt - MB

The samples are categorized as either Application or Technology samples.

sample App
The Application samples are small end-to-end Message Broker applications that show
how to transform and route messages through message flows.
airline reservations
Coordinated Request Reply
DatabaseInput Node
data warehouse
error handler
large messaging
message routing
pager
scribble
Solar Pattern Authoring
user-defined extension
video rental
WBI JDBC Adapter to DatabaseInput Node Migration
Web Service Aggregation
sample Tec
The Technology samples are small Message Broker applications that each show a
specific feature of WebSphere Message Broker.

Controlling and Routing samples


Aggregation, collector node, simplified database routing, timeout processing
File Processing samples
batch processing, file output, managed file transfer, wildcard match.
Industry samples
healthcare, TLOG processor.
Message Formats samples :
CSV, EDIFACT, FIX, SWIFT, X12, XMLNSC namespaces, XMLNSC validation.
Message Transformation samples
JavaCompute node, message map, PHPCompute node, XSL transform.
Monitoring samples
WebSphere Business Monitor
Security samples
security identity propagation, security policy enforcement point (PEP).
Transports and Connectivity samples
Browsing MQ queues, CICS transaction server for z/OS connectivity, CICS Transaction
Server for z/OS channel connectivity, CORBA nodes, eMail, HTTPHeader node, IMS
Synchronous request, JD Edwards connectivity, JMS codes, JMSHeader node, MQHeader
node, SAP callout to a synchronous system, SAP callout to an asynchronous system,
SAP connectivity, SCA nodes, TCPIP client nodes, TCPIP handshake, Twineball example
EIS adapter.
Web Service samples
address book, asynchronous consumer, RESTful Web Service using JSON, SOAP nodes,
web services using HTTP nodes, web service gateway, websphere service registry ans
repository connctivity.
Default configuration
Amb el Wizard fer la configuracio per defecte :

c:\Documents &
Settings\Administrator\IBM\wmbt70\workspace\.metadata\SamplePreparationWizard.log
Qmgr = MB7QMGR:2414 ;
Broker name = MB7BROKER, qMgr = MB7MGR ;
projects in the workspace: FileBatchProcessingSampleFlowProject ;
new execution groups (to deploy): FileBatchProcessingSampleExecutionGroup ;
HealthCheck flow
Get it here.

Once deployed, accessing this url http://9.137.147.65:7080/httpHealthCheck produces


{search for biphttplistener at TCPview to find the HTTP Lister port} :

<Response>
<BrokerName>MB7BROKER</BrokerName>
<BrokerVersion>7002</BrokerVersion>
<BrokerFamily>WINDOWS</BrokerFamily>
<ExecutionGroupName>default</ExecutionGroupName>
<MessageFlowName>httpHealthCheck</MessageFlowName>
<Timestamp>2011-07-04T13:19:37.583412</Timestamp>
<GMT_Timestamp>2011-07-04T11:19:37.583412</GMT_Timestamp>
</Response>
Lets run v7 samples - [1] batch processing sample
This sample shows how to use the FileInput and FileOutput nodes to read different
input files and append them to one output file. It also shows you how to read a
file "as is" from one local input directory and write the file to a different local
output directory.
Links : File processing -> batch -> run the sample.

C:\Program Files\IBM\WMBT700> mqsichangebroker MB7BROKER -f all


C:\Program Files\IBM\WMBT700> mqsistart MB7BROKER
mkdir c:\MQSIFileInput\
mkdir c:\MQSIFileInput\branch_out
mkdir c:\MQSIFileInput\hoffice_in
mkdir c:\MQSIFileInput\hoffice_out
mqsilist
mqsistop MB7BROKER
< set MQSI_FILENODES_ROOT_DIRECTORY to c:\MQSIFileInput >

c:\>set MQSI
MQSI_FILENODES_ROOT_DIRECTORY=c:\MQSIFileInput

mqsistart MB7BROKER
C:\Program Files\IBM\MQSI\7.0> mqsilist
BIP1284I: El intermediario 'MB7BROKER' en el gestor de colas 'MB7QMGR' se est
ejecutando.
BIP8071I: El mandato ha finalizado correctamente.

stop the message flow FileBatchProcessingSample_HOffice


stop the message flow FileBatchProcessingSample_Branch
< Java not installed > => reinstall MB 7.0.0.2

Copy southhamptom_branch.txt file into c:\MQSIFileInput\branch_out directory :


"Southampton postage parcel 23 letter 56"
Restart the FileBatchProcessingSample_Branch message flow =>
the content of the southampton_branch.txt input file is transferred (moved) to
the mqsitransit subdirectory in c:\MQSIFileInput\hoffice_in
Copy winchester_branch.txt file into c:\MQSIFileInput\branch_out directory :
"Winchester postage parcel 27 letter 30" - file moved immediatelly
Copy portsmouth_branch.txt file into c:\MQSIFileInput\branch_out directory :
"Portsmouth postage parcel 12 letter 84" - file moved immediatelly
Look at the mqsitransit subdirectory. This directory is empty because this file
was the third record received.
Look at the hoffice_in.txt file in the hoffice_in subdirectory

Start the FileBatchProcessingSample_HOffice message flow to transfer the file from


the head office input directory to the head office output directory:
c:\MQSIFileInput\hoffice_in\mqsiarchive has a file with timestamp
Output file hoffice_out.txt is created in c:\MQSIFileInput\hoffice_out

c:\MQSIFileInput>type c:\MQSIFileInput\hoffice_out\hoffice_out.txt
Southampton postage parcel 23 letter 56
Winchester postage parcel 27 letter 30
Portsmouth postage parcel 12 letter 84
Lets run v7 samples - [2] address book sample
This sample shows how to use the SOAPInput, SOAPReply and SOAPRequest nodes to
provide and consume a web service. Two sets of example input messages are provided:
one set to call the consumer flow which in turn calls the provide flow, and one set
to ocall the provider flow directly. This sample can also be extended too show how
to set up WS-Security for existing messages flows for both a provider and a
consumer.

Summary of tasks: Message Broker Address Book sample

Create the following projects in the workspace:


AddressBookMessageSet
AddressBook

Add the following WebSphere MQ queues:


ADDRESSBOOK_IN
ADDRESSBOOK_OUT
ADDRESSBOOK_FAULT
JMSREQUESTQ
JMSREPLYQ

Deploy the samples into the following new execution groups:


AddressSampleConsumer
AddressSampleProvider

[a] set up the Address Book sample for SOAP/HTTP :

C:\Program Files\IBM\MQSI\7.0> mqsireportproperties MB7BROKER -e


AddressSampleProvider -o HTTPConnector -n port
7800
BIP8071I: El mandato ha finalizado correctamente.

Select a free port for the TCPIP Monitor : 5353


Set Window -> Preferences -> Run/Debug -> TCP/IP MOnitor to use this local port,
being Host name = 127.0.0.1:7800 ;
Change 2 SOAP Request nodes in AddressBookConsumerFlow.msgflow to this Web Service
URL :
{finsAddress} http://localhost:5353/jwsAddressBook/AddressBookService
{saveAddress} http://localhost:5353/jwsAddressBook/AddressBookService
Change msgflow "Version" field in "Properties" tab.
Redeploy BAR file :
On Project folder, open AddressBook project and open Broker Archives ;
select AddressSampleConsumer.bar file, select "Prepare" tab and click on "Build
broker archive".
Drag AddressSampleConsumer.bar file to AddressSampleConsumer execution group or
right click + "Deploy" + select executionGroup.

[b] set up the Address Book sample for SOAP/JMS :


[-] run the sample :
Broker Development view, expand AddressBook project. Expand Flow Tests. Double
click "AddressBookTests.mbtest to open the file
[end] remove TCP/IP monitor :
window -> preferences -> run/debug -> tcp/ip monitor : select 5353 and "remove"
modify 2 SOAP nodes in AddressBookConsumerFlow.msgflow to use 7800 instead of
5353 port
Lets run v7 samples - [3] web services using HTTP nodes sample
This sample shows how to use MB to front an existing appplication as a web service
- local information center {T400}, T430+MB v9

The Web Services using HTTP nodes sample has two parts:

the Web Service Host sample, which demonstrates how to use a message broker to
provide an interface to a legacy application as a Web service.
the Web Service Client sample, which demonstrates how to call a Web service, and
how to process the reply from the Web service.
From WebSphere Message Broker v6.1 onwards, SOAP nodes are provided to implement
Web services.

Click install and deploy the sample

Summary of tasks: WebServices using HTTP nodes sample


Create the following projects in the workspace: WSHOST_LEGACY1 WSHOST_MSP1
WSHOST_MFP1 WSCLIENT_MSP1 WSCLIENT_MFP1
Add the following WebSphere MQ queues: WSHOST1_IN1 WSHOST1_OUT1 WSHOST1_STATE1
WSCLIENT1_IN1 WSCLIENT1_OUT1
Deploy the samples into the following new execution groups: WSHOST
Now we have

C:\MQSI\9.0.0.0> mqsilist -r
===================================
BIP1284I: El intermediario 'IB9NODE' en el gestor de colas 'IB9QMGR' se est
ejecutando.
-----------------------------------
BIP1286I: El grupo de ejecucin 'WSHOST' en el intermediario 'IB9NODE' se est
ejecutando.
BIP1288I: El flujo de mensajes 'WSHOST_MFP1.WSHOST_WSHOST1' del grupo de ejecucin
'WSHOST' se est ejecutando.
BIP1288I: El flujo de mensajes 'WSCLIENT_MFP1.WSCLIENT_WSCLIENT1' del grupo de
ejecucin 'WSHOST' se est ejecutando.
BIP1290I: El archivo 'WSCLIENT_MFP1\WSCLIENT_WSCLIENT1.esql' est desplegado en el
grupo de ejecucin 'WSHOST'.
BIP1290I: El archivo 'WSHOST_MFP1\WSHOST_WSHOST1.esql' est desplegado en el grupo
de ejecucin 'WSHOST'.
BIP1290I: El archivo 'WSHOST_MS1.dictionary' est desplegado en el grupo de
ejecucin 'WSHOST'.
BIP1290I: El archivo 'WSCLIENT_MS1.dictionary' est desplegado en el grupo de
ejecucin 'WSHOST'.
BIP8071I: El mandato ha finalizado correctamente.
Now we can run the sample and also resolve problems when running samples

Running the Web Service Host sample


When you run the Web Service Host sample, the broker receives and sends back a
SOAP/XML message, over HTTP protocol. The broker is acting as a Web service host.

The broker takes data from this SOAP message, and generates a new message mapped to
a C header file. This new message is sent to a legacy application by using
WebSphere MQ. The legacy application responds, and data from this response is put
into the HTTP reply that is generated by the broker. The broker has fronted a
legacy application as a Web service.

To run the Web Service Host sample:

start the legacy application


Run "legacyservice.exe" from "runLegacyApp.bat" to provide params, as qname =
WSHOST1_OUT1
( at C:\Documents and Settings\Administrator\IBM\wmbt70\workspace\WSHOST_LEGACY1 )
Source code is in "legacyservice.c"

put a SOAP message to the URL that is specified in the WSHOST_WSHOST1.msgflow


HTTPInput node, using any freeware tools available for testing web services and
sending SOAP messages - SOAP tools, SOAP msg builder - use NetTool (XML only), or
CURL, or SOAP UI (with WSDL) or "XML Spy" (30 day trial, complete)
The sample message is in the WSHOST1IN.xml file
( at c:\Documents and Settings\Administrator\IBM\wmbt70\workspace\WSHOST_MFP1 )
and the URL is http://localhost:7080/samplebrokerwshost

Using wget:

set FN=WSHOST1IN.xml
set URL=http://localhost:7080/samplebrokerwshost
"c:\Program Files (x86)\GnuWin32\bin\wget.exe" "%URL%" --post-file="%FN%"
--header="Content-Type:text/xml"
Where have we said that our web-service has a bphttplistener at port 7800 ?

How are samples imported


When using toolkit built-in help, you can install sample objects by clicking on a
link that will issue a command like this:

javascript:liveAction( "com.ibm.etools.mft.eou",

"com.ibm.etools.mft.eou.wizards.sampleprepwiz.SamplePrepWizActiveHelp",
"select, com.ibm.etools.mft.samples.WBMonitor.res,
0" )
It would be good to know how a MQ "runmqsc" command is issued from within a such a
link

"samples.WBMonitor.res" is a directory under "c:\Program Files


(x86)\IBM\SDPShared\plugins"
there we can find files of type BAR, XML and ESQL, but no CMD's
Amunt! Top Amunt!
v9 - IBM Integration Toolkit
XP is not supported in IIB 9. Windows 7 is the lowest supported client version (32
or 64 bit).

We start with this file :

2.127.930.397 IIB_TOOLKIT_V9.0_WINDOWS.zip
Start install by launching installToolkit.bat.
Shared directory (1,5 GB) = C:\Program Files (x86)\IBM\SDPShared ;
Installation Manager v 1.6.2 = C:\Program Files (x86)\IBM\Installation
Manager\eclipse ;
Product (262 MB) = C:\IntegrationToolkit90 ;

"Default Configuration" setup:

Target Environment of Wizard


-----------------------------------------------------------------------------------
----------------------------------------
Summarized resource updates listed below will be applied to installation
[C:\MQSI\9.0.0.0]
All actions are logged to file [SamplePreparationWizard.log] under workspace
directory
[C:\Documents and
Settings\Administrator\IBM\IntegrationToolkit90\workspace\.metadata]

All actions are applied under account: LocalSystem


Queue manager name: IB9QMGR
Queue manager port: 2414

Default integration node details


Integration node name: IB9NODE
Queue manager name: IB9QMGR

To establish why the task failed, examine this wizard's log file which can be found
in the workspace directory
[C:\Documents and
Settings\Administrator\IBM\IntegrationToolkit90\workspace\.metadata]
{bestp}Amunt! Top Amunt!
Toolkit Hints, Tips & Tricks
Prompt for workspace on startup
Windows -> Preferences -> Workbench -> Startup & Shutdown
Discovering the capabilities of WS MB Toolkit v 6 - Hints and Tips

-showlocation option
displays workspace path on top line
-clean option
rebuilds the cache of plugin (and other) information and extends the startup time.
[T430:\WS-BI-MB\ToolKit] Hints_and_Tips_for_WMB_Toolkit.pdf from here
Go to problems tab and select the error line that shows "This project needs to
migrate WTP metadata"
Right mouse click and select "Quick Fix". Select OK to "Migrate WTP metadata".
from here

Per instalar el TKT, primer hem de descomprimir els discs en directoris contigus:
/instbroker/disk1
/instbroker/disk2
/instbroker/disk3
Window -> Show View -> Other -> TCP/IP Monitor
display the TCP/IP monitor on the workbench
De tant en tant, ens conv fer
"Project" -> "Clean" !
"Window" -> "Reset Perspective" = restablir finestres
If we want to see the (XML) message we are handling with at some point of the flow,
put a wire to a MQInput node, and select "Advanced" + "Transaction Mode = none" ;
otherwise mq message can be lost if it is not commited.
flow does not work : what to do ?
mq input node : message domain is not XMLNSC
compute node : compute mode does not propagate LocalEnvironment
Best practices
do NOT use trace node - use "user" trace when needed
use node naming convention, as IC04
Posar el Toolkit en angls : c:\MBTKTv7\
Add the language to the eclipse.ini {yes}

-Duser.language=en
Or add the language to the mb.ini {no}

eclipse
-showlocation
-product com.ibm.etools.msgbroker.tooling.ide
-nl en_US
Configurable message flow properties
When you add a message flow to a BAR file in preparation for deploying it to a
broker, you can set additional properties that influence its run time operation.
These properties are available for review and update when you select the Manage and
Configure tab for the broker archive file.

Flow versioning
It is very important to be sure you are running the flow version you have in mind,
not a previous one.

To assign a flow version number and to verify you have it deployed, we can do:

on any flow, under "User Defined Properties", assign Properties -> Description ->
Version
on the Execution Group, verify you have the correct flow version deployed
Or
use $MQSI Author=Sebastia.Net MQSI$ and $MQSI Subflow 1 Version=v1.3.2 MQSI$ in
"Long Description" field at the "Properties" of the ".msgflow"
then use command
c:\> mqsireadbar -b %TKT%\workspace\BARfiles\cnt_bar.bar -r
BIP1051I: Reading Bar file using toolkit mqsireadbar...
cnt_app.appzip (9/01/14 19:55):
cnt_flow.msgflow (9/01/14 19:55):
Author = Sebastia.Net
Subflow 1 Version = v1.3.2
MB flow version assign MB flow version verify
Keywords are extracted from the compiled message flow (the .cmf file) rather than
the message flow source (the .msgflow file). Not all the source properties are
added to the compiled file. Therefore, add message flow keywords in only these
places:

the label property of a Passthrough node


ESQL comments or string literals
the Long Description property of the message flow
Message flow version and keywords

Start additional instances when flow starts


This property specifies whether all additional instance threads are to start when
the flow starts. Both flow and node-scope instances will start if this option is
set to true. The default value is false.

To set it, select the BAR file on the left pane, expand the "Manage" tab and select
the message flow. Select "Workload management" to display and set the values.

Commit Count
For WebSphere MQ messages, this property specifies how many input messages are
processed by a message flow before a sync point is taken (by issuing an MQCMIT
command). The default value of 1 is also the minimum permitted value. Change this
property to avoid frequent MQCMIT calls when messages are being processed quickly
and the lack of an immediate commit can be tolerated by the receiving application.
Use the Commit Interval to ensure that a commit is performed periodically when not
enough messages are received to fulfill the Commit Count.
This property has no effect if the message flow does not process WebSphere MQ
messages.

Toolkit exe's
C:\Program Files\IBM\WMBT700> dir mqsi*.exe
12/01/2010 12:28 39.664 mqsiapplybaroverride.exe
02/06/2010 15:56 54.512 mqsicreatebar.exe
12/01/2010 12:29 39.664 mqsicreatemsgdefs.exe
12/01/2010 12:39 39.664 mqsicreatemsgdefsfromwsdl.exe
12/01/2010 12:28 39.664 mqsireadbar.exe
5 File(s) 213.168 bytes
Toolkit log
Toolkit writes in {$workspace}/.metadata/.log

Toolkit conectivity
.broker file syntax (expor from MQExplorer):

type BKAS.broker
<?xml version="1.0" encoding="UTF-8"?>
<configmgr crlNameList="" domainName="" host="192.168.1.9" listenerPort="1491"
queueManager="MB7QMGR"
securityExit="" securityExitJar=""
sslCipherSuite="NONE" sslDistinguishedNames=""
sslKeyStore="" sslTrustStore=""
svrconn="SYSTEM.BKR.CONFIG"/>
Thing you can do only from Toolkit
display which Brokers are in a CM domain
assign a Broker to a specific CM (can use "adopt" from Proxy)
Amunt! Top Amunt!
Applying service to the IBM Integration Toolkit
doc

For information about current fixes, follow the link Recommended fixes in the
Download section of the IBM Integration Bus support web page. Click the link for
Version 9.0, and select the updates you want to apply.

Fix : d:\fonts\websphere\mbtkt\mb7000_7002\repository.config

URLs :
updates
extensions

Amunt! Top Amunt!


Clear Case
Revision control sw list, IBM.

CVS
Concurrent Versions System or Concurrent Versioning System, is a client-server free
software revision control system in the field of software development. A version
control system keeps track of all work and all changes in a set of files, and
allows several developers (potentially widely separated in space and time) to
collaborate.

From Toolkit, on a project, we do

right click on a project name


Team -> share project
repos := cvs ;
location := ip/port ;
cvs -> flow : update or check-out ;
flow -> cvs : commit ;
Java versus ESQL
Both Java and ESQL in normal circumstances perform broadly the same. There are some
things which can be done in ESQL which can't in Java, and may perform better, such
as SELECTs against the message tree. If however the customer's skills are
predominantly Java then this would be preferred to save learning a new language.

Amunt! Top Amunt!


MB HealthCheck
Flow troubleShooting :

IH03: Message Broker V7 - message display, test & performance utilities; as


American Express: "don't leave home without it"!
IS03 - MB Message Flow Statistics Visualiser
start accounting :
mqsichangeflowstats <broker> -s -e <EGname> -f <message flow> -c active -t basic -n
advanced -o usertrace
mqsireadlog <broker> -u -e <EGname> -f -o trace.xml
mqsiformatlog -i trace.xml -o trace.log

Stop accounting : mqsichangeflowstats <broker> -s -e <EGname> -f <message flow> -c


inactive -t basic -n advanced -o usertrace
JVM problem determination using Resource Statistics
The following properties are reported (command: mqsireportproperties ?
"mqsichangeflowstats" ?)

Resource Statistics can be found here (MB v8)


(MBX -> expand Brokers -> window -> show view -> resource statistics)
(MBX -> expand EGs -> right-click on EG -> [start or stop or view] [msg flow or
resource] statistics)

InitialMemoryInMB
The initial amount of memory (in megabytes) that the JavaT virtual machine requests
from the operating system for memory management during startup.
Its value may be undefined which is indicated by a value of -1.
UsedMemoryInMB
The amount of memory currently used (in megabytes).
CommittedMemoryInMB
The amount of memory (in megabytes) that is guaranteed to be available for use by
the Java virtual machine.
MaxMemoryInMB
The maximum amount of memory (in megabytes) that can be used for memory management.
Interpretation

how much memory is the JVM using ?


CommittedMemoryInMB - how much memory is currently allocated to the JVM
MaxMemoryInMB - how big this may grow.
how often am I doing garbage collection ?
CumulativeNumberOfGCCollections - Frequent increase in this indicates the garbage
collection (GC) may be excessive. Excessive GC can impact performance.
CumulativeGCTimeInSeconds - If this is increasing at more than 2 seconds per 20
second stats interval then consider increasing the JVM Max Heap size
Inspect any Java Plugin nodes or Java Compute nodes in your message flows to ensure
that you are not creating and deleting many objects that could be reused.
should I change my min or max heap size ?
If your CumulativeGCTimeInSeconds is increasing by more than 2 seconds per stats
interval then look to increase the Max Heap Size to reduce this.
If your UsedMemoryInMB is never close to your InitialMemoryInMB then this indicates
that you are pre-allocating more memory for the heap than necessary and could
reduce the JVM Min Heap Size value for you execution group to a value closer to the
UsedMemoryInMB value.
WSTE MB v7 Administration and Troubleshooting Made Easy - Shah.pdf [T430\\WS-BI-
MB\TroubleShooting]

EG healthcheck
An Execution Group is a process. If we are under AIX, use nmon to display memory
usage. Specifically, verify there is no paging to file system.

If there is paging, everything becomes slow and indicates a problem of capacity,


not performance. So, unless we have a very ineficcient flow, the only solution is
to add physical memory.

Flow eficiency
use references for fields of 3 or more levels, as "InputRoot.XMLNSC.msg.a"
avoid using "SET OutputRoot = InputRoot" if message does not change.
To propagate InputRoot and InputLocalEnvironment, change Compute Mode to
"ExceptionList", selecting "RETURN TRUE"
dont use subscripts
Sample (1) :
do not
SET OutputRoot.XMLNSC.newmsg.aa = InputRoot.XMLNSC.msg.a;
SET OutputRoot.XMLNSC.newmsg.bb = InputRoot.XMLNSC.msg.b;
SET OutputRoot.XMLNSC.newmsg.cc = InputRoot.XMLNSC.msg.c;

but

DECLARE inRef REFERENCE TO InputRoot.XMLNSC.msg;


SET OutputRoot.XMLNSC.newmsg.aa = inRef.a;
SET OutputRoot.XMLNSC.newmsg.bb = inRef.b;
SET OutputRoot.XMLNSC.newmsg.cc = inRef.c;

or better {si newmsg no existe, la declaracin no funciona - LASTMOVE(outRef) da


FALSE}

DECLARE inRef REFERENCE TO InputRoot.XMLNSC.msg;


DECLARE outRef REFERENCE TO OutputRoot.XMLNSC.newmsg;

CREATE LASTCHILD OF OutputRoot.XMLNSC AS outRef NAME 'newmsg';

SET outRef.aa = inRef.a;


SET outRef.bb = inRef.b;
SET outRef.cc = inRef.c;
Sample (3):

do not
DECLARE J INTEGER CARDINALITY(InputRoot.XMLNSC.msg.sum[]);

WHILE i < 100 DO

SET Environment.x = Environment.x + InputRoot.XMLNSC.msg.sum[i].x;


SET Environment.y = Environment.y + InputRoot.XMLNSC.msg.sum[i].y;
SET i = i + 1;

END WHILE;

but

DECLARE sumRef REFERENCE to InputRoot.XMLNSC.msg.sum[1];

WHILE LASTMOVE(sumRef) DO

SET Environment.x = Environment.x + sumRef.x;


SET Environment.y = Environment.y + sumRef.y;
MOVE sumRef NEXTSIBLING;
END WHILE;
Message set health check
use TDS, not CWF
if v8 or v9, use DFDL
Amunt! Top Amunt!
Dubtes Toolkit
an internal error occurred during: "Cleaning up symbolic strings in the WebSphere
Integration Developer index"
conectar MB a Reuters mediante protocolo "TOF", del cual se conoce la API.
Sabiendo la API, lo mejor es implementar el protocolo con Java Compute nodes.
hi ha alguna comanda per veure la versi d'un BAR file ? Solucio
Amunt! Top Amunt!
Toolkit Links
Infocenter
IP04 : designing for performance
Q04 : MB troubleshooting and common pitfalls (debug, etc)
lista exhaustiva de adaptadores : url {Emir, 12/2010}
HTTP transport nodes in MB v6 - url.
Integrating with TCP/IP using MB : url, MATIP & BATAP (airline) & ISO8583
(banking).
MB forum at developerWorks
SOAP SSL example flows (int)
SWIFT or ISO 15022
nice product on top of MB : FTM (Francisco, 2013)
Samples {*****}
ESQL vs Java
Error Handling in WMB : (1) (2).
MQ admin from MB using admin agent
Valid HTML 4.01! Valid CSS!
Updated 20150324 (a)
Uf !

S-ar putea să vă placă și