2000 - sg246154

282
ibm.com/redbooks Business Integration Solutions with MQSeries Integrator Geert Van de Putte Colin Brett Paul Sehorne Sharon Stubblebine Exploring the latest version of MQSeries Integrator Extending the functionality of MQSeries Integrator Providing a single customer view solution

Upload: dgramma

Post on 09-Dec-2015

217 views

Category:

Documents


0 download

DESCRIPTION

2000 - business integration solutions with mq-series integrator

TRANSCRIPT

ibm.com/redbooks

Business Integration Solutions withMQSeries Integrator

Geert Van de PutteColin Brett

Paul SehorneSharon Stubblebine

Exploring the latest version of MQSeries Integrator

Extending the functionality of MQSeries Integrator

Providing a single customer view solution

Business Integration Solutions withMQSeries Integrator

August 2000

SG24-6154-00

International Technical Support Organization

© Copyright International Business Machines Corporation 2000. All rights reserved.Note to U.S Government Users – Documentation related to restricted rights – Use, duplication or disclosure issubject to restrictions set forth in GSA ADP Schedule Contract with IBM Corp.

First Edition (August 2000)

This edition applies to Version 2, Release 0 of MQSeries Integrator, Program Number 5639-F61 for usewith the Windows NT Version 4 Operating System.

Comments may be addressed to:IBM Corporation, International Technical Support OrganizationDept. HZ8 Building 678P.O. Box 12195Research Triangle Park, NC 27709-2195

When you send information to IBM, you grant IBM a non-exclusive right to use or distribute theinformation in any way it believes appropriate without incurring any obligation to you.

Before using this information and the product it supports, be sure to read the general information inAppendix D, “Special notices” on page 253.

Take Note!

Contents

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viiThe team that wrote this redbook. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viiComments welcome. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viii

Part 1. Introduction to MQSeries Integrator V2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Chapter 1. Overview of MQSeries Integrator . . . . . . . . . . . . . . . . . . . . . 31.1 Business integration and the MQSeries Family . . . . . . . . . . . . . . . . . . 31.2 MQSeries Integrator at a glance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.3 The Configuration Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.4 The Control Center . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.5 The message broker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

1.5.1 Persistent store . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.5.2 Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.5.3 Administrative agent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.5.4 Message flow execution engine . . . . . . . . . . . . . . . . . . . . . . . . . 14

1.6 The User Name Server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141.7 Security subsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161.8 Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161.9 Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161.10 Message domains, message sets, message types . . . . . . . . . . . . . . 181.11 MQSeries Integrator applications . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

Chapter 2. Installation and configuration . . . . . . . . . . . . . . . . . . . . . . . 212.1 Installing MQSeries Integrator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.1.1 Check that prerequisites are installed . . . . . . . . . . . . . . . . . . . . . 212.1.2 Insert CD and follow the Install Wizard . . . . . . . . . . . . . . . . . . . . 24

2.2 Post-installation setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272.2.1 Set up security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272.2.2 Set up databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302.2.3 Create an MQSeries Queue Manager. . . . . . . . . . . . . . . . . . . . . 332.2.4 Create a Configuration Manager. . . . . . . . . . . . . . . . . . . . . . . . . 362.2.5 Create a broker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392.2.6 Create a User Name Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

2.3 Setting up the Control Center . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442.3.1 Starting the MQSeries Integrator Services . . . . . . . . . . . . . . . . . 452.3.2 Start the Control Center . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472.3.3 Adding the Log tab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 492.3.4 Set up user roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 492.3.5 Register (create) a broker. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

© Copyright IBM Corp. 2000 iii

2.3.6 Save the work. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522.4 The "Hello world" message flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

2.4.1 Building the message flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532.4.2 Deploying the HelloWorld message flow . . . . . . . . . . . . . . . . . . . 602.4.3 Testing the message flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

2.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

Chapter 3. Introduction to XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673.1 XML concepts and terminology. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

3.1.1 More terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 693.2 The importance of XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

3.2.1 Importance for the MQSeries Family. . . . . . . . . . . . . . . . . . . . . . 713.2.2 Use of XML within MQSeries Integrator . . . . . . . . . . . . . . . . . . . 72

Chapter 4. Advanced setup of MQSeries Integrator . . . . . . . . . . . . . . . 734.1 Using a remote database for the Configuration Manager . . . . . . . . . . 73

4.1.1 Preparing the AIX system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 734.1.2 Configuring DB2 Client access . . . . . . . . . . . . . . . . . . . . . . . . . . 74

4.2 Creating a multi-broker domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 744.2.1 Overview of the MQSeries clustering feature . . . . . . . . . . . . . . . 764.2.2 Creating the MQSeries Integrator Cluster . . . . . . . . . . . . . . . . . . 794.2.3 Creating the Configuration Manager . . . . . . . . . . . . . . . . . . . . . . 854.2.4 Creating the User Name Server . . . . . . . . . . . . . . . . . . . . . . . . . 864.2.5 Creating the brokers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 864.2.6 Using the Control Center to link everything together . . . . . . . . . . 89

4.3 A multi-broker domain in action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 924.3.1 Connecting the application queue managers . . . . . . . . . . . . . . . 924.3.2 Test scenarios in the multi-broker domain . . . . . . . . . . . . . . . . . 944.3.3 Multi-broker versus multiple execution groups . . . . . . . . . . . . . . 95

4.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

Chapter 5. Example message flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . 995.1 Overview of the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 995.2 Using the Message Repository Manager . . . . . . . . . . . . . . . . . . . . . 1025.3 Creating and deploying the message flow . . . . . . . . . . . . . . . . . . . . 1125.4 Details of each node. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

5.4.1 MQInput node COMPLEX.XML. . . . . . . . . . . . . . . . . . . . . . . . . 1135.4.2 XML.PROCESSOR. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1145.4.3 MQInput node COMPLEX.C . . . . . . . . . . . . . . . . . . . . . . . . . . . 1185.4.4 Compute node CWFtoXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1205.4.5 MQOutput nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

Chapter 6. Exploring ESQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1236.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

iv Business Integration Solutions with MQSeries Integrator

6.2 Field manipulations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1246.2.1 Removing a field from the output message . . . . . . . . . . . . . . . . 1246.2.2 Adding new fields in the output message . . . . . . . . . . . . . . . . . 125

6.3 Database operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1266.3.1 Qualifying table and column names . . . . . . . . . . . . . . . . . . . . . 1266.3.2 Usage of keywords THE and ITEM . . . . . . . . . . . . . . . . . . . . . . 127

6.4 The complete ESQL used in testing the scenarios in this chapter . . . 1286.5 XML output message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

Chapter 7. Developing your own plug-in. . . . . . . . . . . . . . . . . . . . . . . 1377.1 Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1377.2 Overview of the requirements for your plug-in . . . . . . . . . . . . . . . . . 137

7.2.1 API requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1387.2.2 Implementation requirements and restrictions. . . . . . . . . . . . . . 139

7.3 Developing a Switch node . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1397.3.1 Design of the Switch node . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1407.3.2 Making the plug-in available in the Control Center . . . . . . . . . . 1417.3.3 Implementation details of the Switch node . . . . . . . . . . . . . . . . 146

7.4 Testing the plug-in during development . . . . . . . . . . . . . . . . . . . . . . 1577.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

Part 2. A Business Integration solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

Chapter 8. Getting a single customer view with MQSeries . . . . . . . . 1658.1 Single customer view as an e-business pattern . . . . . . . . . . . . . . . . 1668.2 Outbound Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

8.2.1 RB_SCV_1message flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1678.2.2 RB_SCV_Request_Endow message flow . . . . . . . . . . . . . . . . . 1888.2.3 RB_SCV_Request_House message flow . . . . . . . . . . . . . . . . . 2108.2.4 RB_SCV_Request_Motor message flow. . . . . . . . . . . . . . . . . . 213

8.3 Inbound flow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2188.3.1 RB_SCV_Backend_Reply message flow . . . . . . . . . . . . . . . . . 2198.3.2 RB_SCV_Backend_Reply_House&Motor message flow . . . . . . 221

Appendix A. Hardware and software specification. . . . . . . . . . . . . . . . 225A.1 Multi-broker setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225A.2 Single customer view application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225

Appendix B. Source code for the SwitchNode plug-in. . . . . . . . . . . . . 227B.1 Header file SwitchNode.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227B.2 Source file SwitchNode.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

v

Appendix C. Using the additional material . . . . . . . . . . . . . . . . . . . . . . 249C.1 Locating the additional material on the Internet . . . . . . . . . . . . . . . . . . . 249C.2 Using the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

C.2.1 System requirements for downloading the Web material . . . . . . . . 249C.2.2 How to use the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249C.2.3 Material for the single customer view application . . . . . . . . . . . . . . 250

Appendix D. Special notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253

Appendix E. Related publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257E.1 IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257E.2 IBM Redbooks collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257E.3 Referenced Web sites. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257

How to get IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259IBM Redbooks fax order form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260

Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261

Abbreviations and acronyms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

IBM Redbooks review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

vi Business Integration Solutions with MQSeries Integrator

Preface

Very often information about a customer is stored in product-centricdatabases. You can imagine an insurance company that has one database foreach type of insurance they sell. However, when customers want to obtaininformation about their current insurance contracts, they want to see a singleview of that information, and not submit a query for each contract they mighthave. This IBM Redbook outlines the messaging techniques that one canimplement to obtain a user-friendly single customer view, using MQSeriesIntegrator.

This redbook explores the features and functionality of the new version ofMQSeries Integrator for Windows NT and provides guidance on installationand configuration. A number of message flows are developed. Thesemessage flows are the implementation of business rules that need to beexecuted by the MQSeries Integrator broker. The redbook also explains howto extend the functionality of MQSeries Integrator with user-written plug-innodes.

The book also describes a Web-enabled single customer view solution. Thissolution uses WebSphere, DB2, MQSeries, and MQSeries Integrator to solvea common business integration problem: how do I get a single view of all mycustomer information when that information is distributed over a number ofsystems?

The team that wrote this redbook

This redbook was produced by a team of specialists from around the worldworking at the International Technical Support Organization, Raleigh Center.

Geert Van de Putte is an IT Specialist at the International Technical SupportOrganization, Raleigh Center. He has five years of experience in the designand implementation of MQSeries-based solutions. Before joining the ITSO,Geert worked in IBM Global Services, Belgium.

Colin Brett is a Systems Specialist in the United Kingdom. He has 10 yearsof experience as a CICS Systems Programmer, with four years as anMQSeries Systems Programmer and Support specialist. Colin providessupport for both IBM internal systems and external customers.

Paul Sehorne is an IBM Certified Solutions Expert - MQSeries. He is teamleader of the MQSeries Advanced Technical Support Team at the IBM DallasSystems Center in the United States. He does technical marketing support for

© Copyright IBM Corp. 2000 vii

MQSeries and MQSeries Integrator including consulting, architectural design,and implementation. He has written or contributed to several white papersand the redbook MQSeries Backup and Recovery, SG24-5222 and has beena speaker at the annual MQSeries Technical Conference.

Sharon A. Stubblebine is a Senior IT Specialist in the United States. Shehas 22 years of experience in the IT field. For the last five years she hasspecialized in the MQSeries family of products.

Comments welcome

Your comments are important to us!

We want our Redbooks to be as helpful as possible. Please send us yourcomments about this or other Redbooks in one of the following ways:

• Fax the evaluation form found in “IBM Redbooks review” on page 267 tothe fax number shown on the form.

• Use the online evaluation form found at http://www.redbooks.ibm.com/

• Send your comments in an Internet note to [email protected]

viii Business Integration Solutions with MQSeries Integrator

Part 1. Introduction to MQSeries Integrator V2.0

The book is divided into two parts. In this first part, we look at the installationand functionality of MQSeries Integrator. We start with an overview of theproduct, followed by some installation and configuration issues. Also, anumber of examples of ESQL and message flows are explained.

Chapter 1, “Overview of MQSeries Integrator” on page 3 provides anoverview of the new product and the key components. It positions the productin the line of products that constitute the MQSeries family.

Chapter 2, “Installation and configuration” on page 21 gives some guidancefor a standard installation of the product and base configuration.

Given the importance of eXtensible Markup Language (XML) in general andin particular in this new version of MQSeries Integrator, Chapter 3,“Introduction to XML” on page 67 discusses XML, provides a glossary ofterminology, and discusses the relationships between terms.

Chapter 4, “Advanced setup of MQSeries Integrator” on page 73 discussessome advanced installation and configuration issues where MQSeriesIntegrator is installed on multiple machines. Also, it shows how the MQSeriesclustering feature can be used to make the different components of theproduct work together.

The three remaining chapters in this part discuss the use of some importantfeatures of the product. Chapter 5, “Example message flow” on page 99discusses a message flow that routes a message through the system.Chapter 6, “Exploring ESQL” on page 123 shows how to use ESQL to writesimple scripts for the transformation of messages. Chapter 7, “Developingyour own plug-in” on page 137 covers adding functionality to the product viauser-written nodes.

© Copyright IBM Corp. 2000 1

2 Business Integration Solutions with MQSeries Integrator

Chapter 1. Overview of MQSeries Integrator

In this chapter we introduce the major components of MQSeries Integratorand a number of concepts that are important to understand. We explain thebuilding blocks of MQSeries Integrator: defining messages and organizingthem in message sets and building message flows that translate businessrules into logic that is executed by the broker.

1.1 Business integration and the MQSeries Family

The new version of MQSeries Integrator is part of the IBM product offering forbusiness integration, based on the messaging transport layer.

At the core of the MQSeries family is MQSeries itself. It provides assuredonce-only delivery of messages across more than 30 industry platforms usinga variety of communications protocols.

MQSeries provides support for applications with a number of applicationprogramming interfaces (MQI, AMI, JMS) in several programming languagesand for a number of communication models (including point-to-point andpublish/subscribe). MQSeries also provides a number of connectors andgateways to other products such as Lotus Domino, Microsoft Exchange,SAP/R3, CICS, and IMS.

MQSeries Integrator extends the messaging capabilities of MQSeries byadding message broker functionality driven by business rules. It provides theintelligence to route and transform messages, the possibility to filtermessages (topic-based or content-based), and database capabilities forenrichment of the messages or for warehousing the messages. Also, itprovides a framework for extending the functionality with plug-ins touser-written or third-party solutions for specific requirements.

MQSeries Workflow is the third component of IBM’s family of products forbusiness integration. It is also based on the messaging technology offered bybase MQSeries, but it adds a further dimension to the integration ofapplications. It’s not only about applications, but about integrating allresources in a business process. It ensures that the right information gets tothe right target, either a person or application, at the right moment in theprocess flow.

© Copyright IBM Corp. 2000 3

Figure 1. The MQSeries family for business integration

1.2 MQSeries Integrator at a glance

The key components in an MQSeries Integrator environment include:

• Configuration Manager and configuration repository• One or more brokers• Control Center• User Name Server• MQSeries Queue Manager(s)• Message Repository Manager (MRM)

Using the Control Center, the MQSeries Integrator administrator definesmessages in the message repository and message flows. A message flow isa series of operations and rules that a broker executes for a retrievedmessage. Message flows are grouped in an execution group. Executiongroups are assigned to a broker.

When a client application puts a message on an input queue of the broker,the broker will retrieve the message and parse it. From that point on, amessage is stored in the common message interface, which is basically a treestructure representing all fields in that message. The broker then executesthe actions that are configured in the message flow and eventually the

MQSeries

MQSeriesIntegrator

MQSeriesWorkflow

Modular Set of Offerings

MQSeries Foundation

Common Look and Feel

Management/Monitoring

Messaging Tools

Family Traits

Workflow, Process FlowApplication ServicesTools

Xform, Rules, RoutingAPI FrameworkTemplates, Utilities

Messaging ServicesStandard FormatsTools

4 Business Integration Solutions with MQSeries Integrator

message arrives at an output queue, ready to be retrieved by another clientapplication.

Figure 2. Overview of MQSeries Integrator

A message flow consists of a number of nodes, usually starting with anMQInput node and ending with one or more MQOutput nodes. An MQInputnode is the encapsulation of a normal MQGET operation, while an MQOutputnode is the encapsulation of a normal MQPUT operation. Between these twonodes, a message flow can contain other nodes that transform the message.A Filter node allows you to specify a Boolean expression for routing themessage. In a Compute node you can specify a script to alter message fields.The script is written in the programming language ESQL, which is anextension of standard SQL. Another important type of node is a Databasenode. These nodes allow you to interact with an external database. You canuse information from a database to enrich a message or to route a message.You can use the message to make updates in the table. It is also possible tostore the message using the Warehouse node. A first example of a messageflow is described in 2.4, “The "Hello world" message flow” on page 53. A more

Chapter 1. Overview of MQSeries Integrator 5

complex message flow is described in Chapter 5, “Example message flow” onpage 99 which also shows how to re-use a message flow within anothermessage flow.

Besides the standard nodes, called IBMPrimitives, you can extend the paletteof nodes with user-written or third-party nodes that perform a specificfunction. Within such a user-written node, you have access to the messagethat flows in and you can create a new transformed message, just like youcan with a Compute node.

1.3 The Configuration Manager

An MQSeries Integrator system is controlled by the Configuration Manager;the components and resources managed by the Configuration Manager makeup the broker domain. The Configuration Manager maintains the brokerdomain configuration in the configuration repository. The Control Center isused to create and modify this configuration.

The Configuration Manager is the main component of the MQSeriesIntegrator runtime environment, and serves three main functions:

• It maintains configuration details in the configuration repository. This is aset of database tables that provide a central record of the broker domaincomponents.

• It manages both the initialization and deployment of the broker andmessage processing operations in response to functions performed usingthe Control Center.

• It checks the authorities of defined user IDs, for the authority to initiatethose actions.

The Configuration Manager provides services to the other broker domaincomponents, providing configuration updates in response to Control Centeractions.

The Configuration Manager requires:

• A set of tables in a database, known as the configuration repository. Thisdatabase must be created using DB2 Universal Database for Windows NT.The Configuration Manager uses a Java Database Connectivity (JDBC)connection to this database.

• A set of tables in a database, known as the message repository. Thisdatabase must be created using DB2 Universal Database for Windows NT.

6 Business Integration Solutions with MQSeries Integrator

The Configuration Manager uses an Open Database Connectivity (ODBC)connection to this database.

• A set of fixed name queues defined on the MQSeries Queue Manager thathosts the Configuration Manager. This MQSeries Queue Manager mustexist on the same physical system as the Configuration Manager, and isidentified at the time the Configuration Manager is created.

These queues are created when the mqsicreateconfigmgr (includingassociated variables) command is executed through either the GUI or thecommand prompt. No actions are required by the administrator to add therequired definitions.

• A server connection, defined to the MQSeries Queue Manager that hoststhe Configuration Manager. This connection is used by all instances of theControl Center that communicate with the Configuration Manager.

• Sender and receiver channels to each broker in the broker domain exceptfor a broker that would share its queue manager with the ConfigurationManager.

1.4 The Control Center

The Control Center is used to configure and control the broker domain. Thisworks in association with the Configuration Manager, passing messages backand forth as information is requested and making updates to the components.

Chapter 1. Overview of MQSeries Integrator 7

Figure 3. Relationship between the Control Center and the Configuration Manager

Any number of Control Center instances can be installed and invoked. TheControl Center depends on MQSeries for Java for its connection with theConfiguration Manager. The Control Center may be installed on the samephysical system as the Configuration Manager or on any system that canconnect to the Configuration Manager. The Control Center dynamicallycreates a client connection to connect to the Configuration Manager’s queuemanager using the information provided at invocation.

The Control Center is structured to provide a series of views on theconfiguration and message repositories. Views are selected by choosing oneof five roles; “All Roles” shows every view. Other roles include message flowand message set developer, message flow and message set assigner,operational domain controller, and topic security administrator.

The Control Center is the business administration tool used to definemessage flows for applications and to access the databases and resourcesused by MQSeries Integrator. This interface allows the manipulation of thefollowing resources:

ODBCconnection

Queue Manager

ConfigurationManager

JDBCconnection

Configurationrepository(shared/deployed data)

Messagerepository

MQSeries Client for Java

TCP/IP connection

Local configuration data Control Center

8 Business Integration Solutions with MQSeries Integrator

• Message flows• Message sets• Brokers• Collectives• Principals

These resources are stored in the configuration repository database and inthe message repository database.

The Control Center can be used to:

• Develop, modify, assign, and deploy message flows.

• Develop, modify, assign, and deploy message sets.

• Define the broker domain topology and create collectives.

• Create and modify access control lists (ACLs) to control publish/subscribesecurity.

• View status information.

The Control Center manages the configuration data for a particularworkspace. There are three different versions of this data. When the ControlCenter is started, the local version of the configuration data is presented. Thethree presentations are:

Local A copy of configuration data on which a user is working. Toobtain a local copy of configuration data, you need to check outthe resources from the shared copy. While checked out, otherusers are prevented from updating the resource.

Any changes made to a local version will not be visible to otherusers until the status of the resource is changed by checking inthe resource.

Shared A version of the configuration data that is shared by all the usersof the Control Center. Once resources are checked out to thelocal workspace, they can be modified, and once modifiedchecked in.

Deployed This is the active version of configuration data that is operationalat the broker.

Chapter 1. Overview of MQSeries Integrator 9

1.5 The message broker

Figure 4. Overview of a broker

The message broker consists of a number of processes. For each executiongroup assigned to a broker, the broker creates an additional data flow engine.As explained before, an execution group is a way of grouping message flows.

Any number of brokers can be added within a broker domain. More than onebroker may reside on a physical system. Each broker defined will require aunique MQSeries Queue Manager. A single broker can share the MQSeriesQueue Manager of either or both the Configuration Manager or User NameServer.

The broker is made up by a number of other components:

• Controller

• Message Format Services. These support definitions of metadata thatdescribe the data format within messages.

• Persistent State Datastore. The broker has a mandatory database to holdall persistent state data needed by the broker. This includes for example:

- The deployed message flow definitions- Persistent subscriptions- Publish/subscribe neighbors

Broker

Queue ManagerBroker database

ODBCconnectionExecution group

Message dictionary

Message flowMessage flow

10 Business Integration Solutions with MQSeries Integrator

Each broker requires:

• A set of tables in a database to hold the broker’s local data. This isaccessed using the ODBC connection. These tables are also referred toas the broker’s local persistent store.

• A set of named queues on the queue manager associated with the brokerdomain.

- Again no actions are required by the administrator to add thesedefinitions. They are added during execution of the mqsicreatebrokercommand.

• Each broker needs its own queue manager. It can share the queuemanager hosting either or both the Configuration Manager and optionalUser Name Server.

- Since the broker uses a set of predetermined queue names, thiscreates the dependency of an MQSeries Queue Manager per broker.

Creating the broker on the system on which the broker component is installedis not automatically recorded in the configuration repository. The ControlCenter must be used to create the reference. Creating a reference does thefollowing:

• Stores the broker information in the configuration repository.

• Defines a default execution group on this broker. Further execution groupscan then be defined.

• After creating a broker reference, it needs to be deployed to take effect.The deploy action:

- Initiates communication between the Configuration Manager and thisbroker.

- Initializes the broker so that it is ready to execute message flows.

• For operation a broker requires both configuration and initialization data.Configuration and initialization data are logically separate and are storedin different physical repositories.

Configuration data defines the broker’s operational set up. The master copy isstored in the Configuration Manager which is centrally managed. It is alsocached to facilitate fast restart and to make sure the broker continues tooperate if connection to the Configuration Manager is lost.

Initialization data defines the bootstrap parameters needed by the broker andis physically stored in the registry of Windows NT. Broker initialization data ismade up of the following:

Chapter 1. Overview of MQSeries Integrator 11

• Filepath, the root of the file system where MQSeries Integrator is installed.

• WorkPath, location of a work directory for MQSeries Integrator.

• DataSourceName, datasource name (ODBC) for the broker’s localpersistent storage.

• DataSourceUserID, user name used for accessing the broker database.

• DataSourcePassword, password used for accessing the broker database.

• QueueManagerName, name of the queue manager associated with thisbroker.

• InternalQueueName, an internal queue used for configuration purposes.

• Language, an identifier for help and message texts.

• Version, a version number.

The data is initialized during installation of the broker and may be modified asa function of broker administration.

Each broker instance needs an assigned, everlasting and fixed name. This isthe Broker Instance name. This name, which is similar to the static identifierassigned to databases before they are created, is used to distinguish tablespertaining to one broker from another where multiple brokers have been setup using the same database.

1.5.1 Persistent storeThe broker (as opposed to the Configuration Manager) has a mandatorydatabase that holds all persistent state data needed by the broker. The statedata includes the following:

• A local cache of broker configurations, stored in an optimized format tofacilitate quick restart.

• The operational state of the broker, which message flows are enabled, etc.

• A table of durable subscriptions.

• A table of retained publications.

In order to manage this state, the broker requires a persistent store. Thepersistent store is a relational database that the broker accesses usingstandard JDBC/ODBC interfaces.

1.5.2 ControllerThe controller is the main control process for the broker. Its purpose is tomonitor a table of broker definitions to ensure that the defined broker

12 Business Integration Solutions with MQSeries Integrator

processes (and only those processes), are actually running. To do this thecontroller needs to notice changes to both the table and process state andmake the process state reflect the table.

When the controller starts, it will create an internal cached broker definitiontable by loading information from the broker definition table, which is from thepersistent store. This allows the controller to determine which child processesit needs to spawn, one for each Execution Group required and one for theadministration agent, always created and kept active.

If any one child process dies, the controller process will check the internaldefinition table for this process and perform the action indicated in that entry,usually to restart the process. Also the controller will start a thread that isresponsible for waiting for the broker definition table to change. When thishappens the controller process reads the whole broker definition table andcompares with the internal broker definition table. Any differences will then beresolved by starting or stopping child processes.

There will be only one controller process in a correctly installed system, andonly that controller process ever starts other broker processes.

If the controller process fails and is restarted, it will look for orphanedadministrative agent and MessageFlowEngine Processes. If any are found,the controller will attempt to kill them before starting its own child processes.If unable to kill them, the controller will start up its own children and report onthose it could not kill.

On Windows NT the controller runs as a Windows NT Service.

1.5.3 Administrative agentThe administrative agent manages the updates to the broker definition table.It will monitor the broker’s configuration and administrative queues andprocess the corresponding messages it receives to create, delete, or modifyan entry in the table and to start and stop the broker.

It can run as a separate process from the controller. This is so as not tocompromise the reliability of the monitor. It is permissible to run as oneprocess, but robustness of the system will be weaker.

Configuration messages are routed to either the controller to start or stopexecution engines or to a specific execution engine.

Chapter 1. Overview of MQSeries Integrator 13

1.5.4 Message flow execution engineA message flow execution engine is an environment supporting execution ofbusiness message flows. The execution engines are started and managed bythe controller, with each typically running its own process.

The broker installation process stores the code that implements the messageflow nodes as loadable implementation libraries (*.lil) in the broker’sexecutable directory.

When the message flow execution engine starts up it will initialize itself andwill then load all the lils it can find in the bin directory. This implies that allmessage flows on a machine can have the same capability regarding nodeand message classes.

When such a message flow execution engine is started for the first time it willhave a default configuration that is sufficient for it to be able to respond toconfiguration messages. When the administrative agent receives aconfiguration request for a particular execution engine it passes the requestto the engine, causing it to update its configuration as per the instructions inthe message. The configuration updates have the following properties:

• All configuration changes are made transactionally; either all changes inone configuration message are made or none of them are made.

• All configuration changes are made immediately and safely; messageprocessing ceases just before changes are made and resumes withchanged behavior immediately afterwards.

• All configuration changes are made persistently; once changes are made,restarting a message flow (or machine) will automatically configure itselfto its last known state.

• The configuration messages may themselves be processed undertransactional control so that either several brokers get a corresponding setof changes or none of them get any changes.

1.6 The User Name Server

The following diagram shows the role and place of the User Name Server inthe MQSeries Integrator security hierarchy.

14 Business Integration Solutions with MQSeries Integrator

Figure 5. Role of the User Name Server

This is an optional resource. If no use of publish/subscribe is planned in thebroker(s), no topic security is required, and neither is the User Name Server.It is much easier to include in the broker domain when first designed, ratherthan add at some later date when requirements change.

The User Name Server monitors the underlying security subsystem,accessed via the Windows NT User Manager, and provides information aboutusers and groups that it shares with the Configuration Manager and brokers.

Message flows that give publish/subscribe service to applications mightrequire topic security. This gives the ability to control the authority of theapplication, based on the user ID they are running under, to do the following:

• Publish on topics

• Subscribe to topics

• Request persistent delivery of messages

Creation of the User Name Server defines the following resources:

• A set of fixed name queues, defined on the MQSeries Queue Managerhosting the User Name Server and identified during creation. ThisMQSeries Queue Manager may be shared with the ConfigurationManager, broker, or both.

SecuritySubsystem

User Name Server

Queue Manager

Queue Manager

ConfigurationManager

Queue Manager

Broker

Chapter 1. Overview of MQSeries Integrator 15

1.7 Security subsystem

The Windows NT User Manager is populated with five new MQSeriesIntegrator groups to which connection is required to enable users to usevarious features and functions of MQSeries Integrator. If authorized usersselect their required role in user preferences while using the Control Center,they will be able to see and select the tabs required to perform those roles.

Further security is possible for the publish/subscribe function. For this furthersecurity to be available the optional User Name Server must be created.

1.8 Databases

The MQSI components use databases to store configuration and operationalinformation. These databases are used to provide a persistent store.

The Configuration Manager requires two sets of tables to support both themessage repository and the configuration repository. These are created andinitialized when the Configuration Manager is created, and can be in a singledatabase or across two separate databases. Access can be by either aremote or local connection.

Normally three databases will be created, one each for ConfigurationManager, message repository, and broker.

The broker needs a set of database tables to manage its operation. Theseare created within the same database as the configuration repository or themessage repository or both. Tables for each broker can be in the samedatabase as tables belonging to another broker or a separate database.Access can be by either a remote or local connection.

1.9 Dependencies

MQSeries Integrator has several dependencies. MQSeries Integrator isheavily dependent on the facilities of MQSeries messaging to provideconnectivity, message integrity and some transactional support. A summaryfollows to help show the demands that MQSeries Integrator will place on thesystem:

• Queue Managers. A single MQSeries Queue Manager can host only onebroker. The Configuration Manager and User Name Server both dependon an MQSeries Queue Manager, but can share with each other and thebroker, or both.

16 Business Integration Solutions with MQSeries Integrator

• Communications. A network of MQSeries Queue Managers is required tosupport MQSeries Integrator, and the connectivity must be defined. Anysupported communication protocol may be used. Windows NT supports:

- SNA LU6.2- SPX- NetBIOS- TCP/IP

The client/server connection between the Control Center and theConfiguration Manager is limited to using TCP/IP.

• Configuration Manager. The Configuration Manager depends on anMQSeries Queue Manager with a set of fixed named queues and a serverconnection channel. The queues and channel resources are definedduring creation of the Configuration Manager.

A sender and receiver channel pair are also required to be able tocommunicate with each broker in the broker domain, except for the broker(if so defined) created on the same host MQSeries Queue Manager.

• Broker. Each broker depends on a dedicated MQSeries Queue Manager.A broker may not share it with another broker. A broker may, however,share the MQSeries Queue Manager with either or both of ConfigurationManager and User Name Server.

A set of fixed name queues that are defined at broker creation arerequired, as are sender and receiver channels to allow communicationwith the Configuration Manager. Further sender and receiver channels arealso required to allow communication with the User Name Server.

A sender and receiver channel pair are also required to communicate withall brokers in the same collective, or to which it is identified as a neighborin the topology.

• Application. Each application using MQSeries Integrator must be able toconnect to an MQSeries Queue Manager in the MQSeries network toallow it to place messages on the queue serviced by the message flowrequired.

Each application retrieving messages from an application from a queuewritten to by message flow must be able to connect to the queue managerthat owns the queue.

If the application retrieving messages is a subscriber to apublish/subscribe service, the messages it receives are propagated to thebroker to which it has subscribed, regardless of the proximity of the brokerand associated queue manager hosting the publish/subscribe service.

Chapter 1. Overview of MQSeries Integrator 17

• User Name Server. The User Name Server depends on an MQSeriesQueue Manager with a set of fixed named queues. Sender and receiverchannel pairs are also required for communication with the ConfigurationManager and every broker in the broker domain to which it providesprincipal definitions. The queues are defined during the creation of theUser Name Server.

• Databases. MQSeries Integrator components use databases to storeconfiguration and operational data. A summary follows:

- The Configuration Manager needs two independent sets of tables tosupport the message repository and configuration repository.

The tables are created and initialized during Configuration Mangercreation. The two repositories can share the same database, whichmust be DB2. The configuration must have a remote or localconnection to the database, or databases.

- Each broker needs access to a set of tables to support its operation.

These tables are created and initialized during broker creation. Theycan be created in and can share the same DB2 database as theconfiguration repository, message repository, or both.

Subsequently defined brokers can share the same tables since eachentry on each table row, identifies an individual broker. If preferredseparate databases, and thus separate tables can be set up for eachbroker.

The broker requires either a local or remote connection to thedatabase.

1.10 Message domains, message sets, message types

MQSeries Integrator makes a first distinction between self-defined messagesand predefined messages. Self-defined messages use the XML standard tostructure their content. We will also refer to this type of messages as genericXML messages. To use self-defined messages you do not have to doanything specific.

MQSeries Integrator considers two views of a message: the logical view andthe physical view. The logical view of message is the structure of a message:its fields, the order and the relationship between the fields. A message mighthave four fields:

1. Employee number

2. Request type

18 Business Integration Solutions with MQSeries Integrator

3. Order number

4. Work department

Applications receiving and sending these kinds of messages know themeaning of each field and its characteristics. They know that, for example,employee number, request type and order number are six-character fieldsand that work department is a 3-byte character field.

The physical view of the message, also called the wire format, is thesequence of bits that build up the message. For the above message, thephysical view is:

000110NEW 999999AAA

For predefined messages, you need to make MQSeries Integrator aware ofthe logical view and the physical view of the message. For this purpose, youuse the Control Center. If you have already defined some messages using theMQSeries Integrator Version 1 product, you can use the NEONFormatter tomaintain or add predefined messages.

Knowing all this, we can specify what the message domain is. It identifies forthe broker where the look for the actual definition of a message:

1. XML for self-defining messages

2. MRM for messages defined using the Control Center

3. NEON for messages defined using the NEONFormatter

4. BLOB for messages that have no definition

A message type is the definition of the logical view of a message. Messagetypes are grouped in message sets. You can think of a message set as thecollection of messages types used in a single application or project.

The last characterization of a message is the message format. This describesthe physical view of a message, the sequence of bits that make up themessage. The message format can have three values: XML, PDF and CWF.Note that PDF does not stand for Portable Document Format. It is a messageformat that is used in some financial applications. Custom Wire Format(CWF) is a format using data types in common programming languages. TheXML format is for messages that comply with a DTD. For a discussion on XMLand DTD, please refer to Chapter 3, “Introduction to XML” on page 67.

Chapter 1. Overview of MQSeries Integrator 19

1.11 MQSeries Integrator applications

MQSeries Integrator supports two communication models for applications. Inthe point-to-point model, an application is putting a message on a queueserviced by a broker. When the message has passed through the messageflow, the broker puts it on a queue serviced by another client application. Thesecond model is known as publish/subscribe. Applications wishing to receivemessages will create a subscription on a topic. Applications wishing to sendmessages will create a publication for a topic. Publisher and subscriber areunaware of each other. The broker makes sure that publications are sent tothe correct subscribers. Subscriptions can be topic based and/or contentbased.

When sending messages to a queue serviced by a broker, MQSeriesIntegrator needs to know something about the message. There are two waysto provide this information:

1. Your application prefixes the user data of the message with the MQSeriesIntegrator header, MQRFH or MQRFH2.

2. The MQSeries Integrator administrator has provided the necessaryinformation in the configuration of the MQInput node. Basically, thisinstructs the broker to handle all messages on this queue as if they belongto the configured message domain, message set, and message type.

Applications that can use the MQRFH or MQRFH2 header provide the sameinformation. If messages have an MQRFH or MQRFH2 header and at thesame time the MQInput node has values for message domain, set, and type,the broker will check the values. When a message has conflicting informationin the MQRFH or MQRFH2 header, the broker will handle this as a failure.Note that the MQRFH header was used in earlier publish/subscribeapplications and in MQSeries Integrator Version 1 applications. The newversion does support the older MQRFH header.

If publish/subscribe messages have no MQRFH or MQRFH2 header, thebroker will rely on the topic information in the properties of the MQInput node.But existing publish/subscribe applications will normally already have theMQRFH header. For full use of the broker, it might be necessary to changethese applications to use the MQRFH2 header.

20 Business Integration Solutions with MQSeries Integrator

Chapter 2. Installation and configuration

In this chapter we explain the steps necessary to install MQSeries Integratorand to get it running in a basic configuration. This involves databaseconfiguration and the creation of a number of Windows NT Services. Finallywe use the Control Center to develop a simple HelloWorld message flow andshow how to deploy it and test it.

2.1 Installing MQSeries Integrator

The following is a summary of the steps required to install the MQSeriesIntegrator product, set up a working MQSeries Integrator environment, andstart the Control Center. In this chapter, we investigate the installation andconfiguration on a single machine. Configurations where multiple machinesare involved are discussed in Chapter 4, “Advanced setup of MQSeriesIntegrator” on page 73.

If you follow all the steps in this chapter, you should have at the end acomplete and working MQSeries Integrator environment on a single machine.

2.1.1 Check that prerequisites are installedThe following components must be installed:

1. DB2 Enterprise Edition V6.1.

While the broker can run with Microsoft’s SQL Server and while the NeonNodes can use Sybase’s database product, the new ConfigurationManager requires DB2 Enterprise Edition V6.1. If you have installed DB2already, you can verify the version by clicking:

Start -> Programs -> DB2 for Windows NT -> Control Center

© Copyright IBM Corp. 2000 21

Figure 6. Tools menu of the DB2 Control Center

Go to the Tools menu option and select License Center. After selectingthe name of your system, you should verify that the installed product isindeed Enterprise Edition and the version information field is set to 6.1, asshown in Figure 7.

22 Business Integration Solutions with MQSeries Integrator

Figure 7. License Center of DB2

2. MQSeries 5.1 Server and Client.

When installing the MQSeries product, you should make sure that youselect the Client component, including the MQSeries Java client. TheMQSeries Integrator Control Center component uses an MQSeries Clientconnection to the Queue Manager owned by the MQSeries IntegratorConfiguration Manager component.

3. MQSeries 5.1 CSD2.

To verify the level of your MQSeries installation, you can launch Notepadto show you the file memo.ptf by clicking:

Start -> Programs -> IBM MQSeries -> MQSeries Service Level

Look for the following text string:

This memo.ptf file corresponds to the third CSD...

MQSeries Integrator requires the second CSD, while we used the third CSDat the time of writing. You can find the latest level of MQSeries and downloadit from the following Web site:

http://www-4.ibm.com/software/ts/mqseries/support/summary/wnt.html

Chapter 2. Installation and configuration 23

2.1.2 Insert CD and follow the Install WizardTo begin installation, do the following:

1. Insert the MQSeries Integrator CD into the CD drive of the PC. If autorundoes not start the install procedure, then click:

Start -> Run D:\setup.exe (where D is the CD drive letter)

2. Follow the InstallShield Instructions.

a. Accept the License conditions. It is not possible to install MQSeriesIntegrator unless you do so.

3. Click Browse to choose a different install directory. This provides anopportunity to choose a shorter name if you wish. You may also wish toselect another disk on the PC.

- Click Browse.

- Enter for example, D:\Program Files\MQSIV2

- Click Yes to create the new directory.

- Click Next to continue the install.

4. Select a Full install.

5. Accept the default Program Folder.

6. Select the MQSI V1.1 DB2 compatible libraries.

7. Click Finish to end.

8. Reboot the computer once the installation has finished.

Figure 8 through Figure 12 show the windows of the MQSeries IntegratorInstallShield processing followed by us.

24 Business Integration Solutions with MQSeries Integrator

Figure 8. Installation options

Figure 9. Selecting the programs folder

Chapter 2. Installation and configuration 25

Figure 10. Specifying the version 1 database libraries

Figure 11. Installation overview window

26 Business Integration Solutions with MQSeries Integrator

Figure 12. Setup complete

2.2 Post-installation setup

The following steps will configure our Windows NT System to use MQSeriesIntegrator Version 2.0.

In this example a single MQSeries Queue Manager will be used to host theMQSeries Integrator Broker, Configuration Manager, and User Manager.Three DB2 databases will be created for use by MQSeries Integrator. Thenames chosen are arbitrary, so we chose the following names for ease of use.Whatever names you choose should be substituted throughout yourinstallation.

• Message Repository Database: MQSIMRDB

• Configuration Manager Database: MQSICMDB

• Broker Database: MQSIBKDB

The MQSeries Queue Manager will also be created. The same name will beused for the MQSeries Queue Manager as for the broker. Both will be MQSI.

2.2.1 Set up securitySecurity is managed by using five Windows NT user groups created duringthe MQSeries Integrator install process. Depending on the access needed,

Chapter 2. Installation and configuration 27

users should be connected to one or more of the groups. For the purpose ofthis exercise, users are to be connected to all five security groups.

Open the Windows NT User Manager by clicking:

Start -> Programs -> Administrative Tools(Common) -> User Manager

Figure 13. Setup of Windows NT Security

Double-click the target user ID.

28 Business Integration Solutions with MQSeries Integrator

Figure 14. Updating the user’s security profile

Click the Groups button.

Figure 15. Updating group memberships

Chapter 2. Installation and configuration 29

Select the following groups from the Not member of pane (use the Ctrl key formultiple selections):

• MQBRKRS

• MQBRDEVT

• MQBRASGN

• MQBROPTS

• MQBRTPIC

• If required, also select group MQM which pertains to MQSeries security.Users creating or managing MQSeries Queue Manager resources willrequire connection to this group. Full use of MQSeries Integrator requiresthe creation and setup of an MQSeries Queue Manager.

Click the Add button.

Click the OK button to finish.

2.2.2 Set up databases1. Create the databases (if your names are different from the ones we chose,

do not forget to substitute your values.)by clicking:

Start -> Programs -> DB2 for Windows NT -> DB2 Command LineProcessor

Or execute the following commands:

-Create database MQSIMRDB

-Create database MQSICMDB

-Create database MQSIBKDB

-quit

2. Define the ODBC connections for each database by clicking:

Start -> Programs -> DB2 for Windows NT -> Client ConfigurationAssistant

30 Business Integration Solutions with MQSeries Integrator

Figure 16. DB2 Client Configuration Assistant window

a. Select the databases (one at a time).

b. Click the Properties button.

Figure 17. ODBC configuration window

Chapter 2. Installation and configuration 31

c. Check Register this Database for ODBC.

d. Click OK.

e. Click OK (to close the message box).

f. When all three database are done, click Close to finish.

3. Authorize user(s) to the database

When DB2 was installed on our machine we accepted the default user IDand password pair db2admin/db2admin for the DB2 administrator user ID.This is why this pair will be used throughout the configuration where a userID and password are required for access to DB2 resources.

The security setup is also the most straightforward, to meet our goal ofgetting MQSeries Integrator and associated Windows NT services up andrunning. In the setup below, any full administrator user ID would be okay.

a. Click Start -> Programs -> DB2 for Windows NT -> Control Center

b. Enter the DB2 user (db2admin) and password (db2admin)

c. Click + to the left of each item to expand:

- Computer name

- Instances

- DB2

- Databases

d. Right click on each database and select Authorities.

e. Click Add User.

f. Select the intended user.

g. Click OK.

h. Select the user you just added to the view.

32 Business Integration Solutions with MQSeries Integrator

Figure 18. Updating the database authorities

i. Click Grant All.

This changes the crosses to ticks for each selected user, as shown inFigure 18.

j. Click OK.

2.2.3 Create an MQSeries Queue ManagerIn theory, you do not need to create the queue manager before you create theother MQSeries Integrator components. However, by doing so, you can bettercontrol how the queue manager is created and you do not need to revisit theconfiguration of the queue manager at a later stage. For example, thecommand to create the Configuration Manager creates the needed queuemanager if it does not yet exist. However, that command does not create theMQSeries listener that you need for the Control Center.

We will create an MQSeries Queue Manager named MQSI with associatedlistener using port 1414, the default port. The dead-letter queue will be calledSYSTEM.DEAD.LETTER.QUEUE. There is no requirement for a defaulttransmission queue.

Chapter 2. Installation and configuration 33

1. Click Start -> Programs -> IBM MQSeries ->MQSeries Explorer

2. Right-click Queue Managers and select New -> Queue Manager.

Figure 19. Queue Manager creation - Step 1

3. In the Queue Manager field, enter MQSI.

4. Check Make this the default queue manager.

5. The Def Transmission Queue field is not required.

6. In the Dead Letter Queue field, enter SYSTEM.DEAD.LETTER.QUEUE.

7. Click the Next button to continue.

34 Business Integration Solutions with MQSeries Integrator

Figure 20. Queue Manager creation - Step 2

8. Check Use circular logging. Consider increasing the values for logging ifyou will be working with large or complex message flows. Suggestedvalues are 1024 for Log File Size and 5 for Log Primary Files.

9. Click Next to continue.

Figure 21. Queue Manager creation - Step 3

Chapter 2. Installation and configuration 35

10.Check Create Server Connection Channel to allow for easyadministration using the MQSeries Explorer.

11.Click Next to continue.

Figure 22. Queue Manager creation - Step 4

12.Check Create listener configured for TCP/IP.

13.In Listen on port number box, enter 1414.

14.Click Finish to complete creation of the MQSeries Queue Manager.

If you used a non-standard name for the Dead Letter Queue, you’re supposedto create this queue yourself using either MQSeries Explorer or runmqsc.

2.2.4 Create a Configuration ManagerTo create a Configuration Manager, use the Command Assistant. TheCommand Assistant generates a command that can be executedindependently in a DOS window or from within the GUI accessed by thefollowing path. Click:

Start -> Programs -> MQSeries Integrator Version 2.0 -> CommandAssistant -> Create Configuration Manager

or enter:

mqsicreateconfigmgr -i userid -a password -q MQSI-s MQSI -nMQSICMDB -m MQSIMRDB

36 Business Integration Solutions with MQSeries Integrator

To see the meaning and use of the identifiers preceding the values in theabove command, review the following figures. The identifiers appear inparentheses after the text field in each shaded text box.

The Command Assistant windows work as follows. We provide theinformation for required (and some nonrequired) fields. As each field iscompleted, the executable command is added to the lower half of the window.Each text field has a field delimiter value that precedes our value, which issubstituted into the built-up command. It will take more than one window tobuild the full executable command.

We have already chosen the names of our repository databases andMQSeries Queue Manager. Since each broker requires its own MQSeriesQueue Manager, we decided to name the broker with the name of theMQSeries Queue Manager to both reflect and identify this relationship; in thiscase both will be named MQSI.

Figure 23. Configuration Manager creation - Page 1 of 3

The service user ID and service password supplied above are used to startthe Configuration Manager Windows NT Service task. Using the user ID of aDB2 administrator means that further user ID and password pairs are notrequired to allow access to an individual database, since the user ID theservice task is running under has full DB2 authorities to our databases.

Chapter 2. Installation and configuration 37

Note: Changing the password for the supplied user ID will prevent theConfiguration Manager Windows NT Service task from initializing. If thepassword changes, then use the MQSeries Integrator Command Assistantand modify the Configuration Manager, supplying the changed values. This isjust one of the reasons we found that caused us to use the main DB2 installuser ID and password pair when setting up the environment.

The Configuration Manager needs an MQSeries Queue Manager. Since itcan share the MQSeries Queue Manager used by the broker (and also theUser Name Server), the one MQSeries Queue Manager MQSI was usedthroughout for ease of setup and configuration. If you use multiple MQSeriesQueue Managers, your values will be different.

Figure 24. Configuration Manager creation - Page 2 of 3

The names in the ConfigMgr Database Name and MRM ODBC Data SourceName fields are the names used when we created our DB2 databases (andODBC connections) earlier. Because the user ID and password that weprovided previously, for the Configuration Manager Windows NT Service taskto be started under, has full access to both databases, no separate userID/password pairs are needed to allow access to either database.

38 Business Integration Solutions with MQSeries Integrator

Figure 25. Configuration Manager creation - Page 3 of 3

You will have an opportunity to review the fully built executable command.Then click Finish to execute the command and create a Windows NT ServiceTask.

Figure 26. Configuration Manager creation successful

The Command Successful window informs you that the create configurationManager Windows NT Service task command has been successfullyexecuted. Do not start the service at this time.

2.2.5 Create a brokerTo create a broker, again use the Command Assistant. The CommandAssistant generates a command that can be executed independently from aDOS window. Click:

Start -> Programs -> MQSeries Integrator Version 2.0 -> CommandAssistant -> Create Broker

Chapter 2. Installation and configuration 39

or enter:

mqsicreatebroker MQSI -i userid -a password -q MQSI -s MQSI -nMQSIBKDB

The Command Assistant works similar as before. The name of the broker isset to MQSI, which is also the name of the Queue Manager for this brokerand for User Name Server. The user ID associated with the Windows NTService task is set to db2admin as before.

Figure 27. Broker creation - Page 1 of 3

The name of the database for the Broker is MQSIBKDB. If you selectedanother name in 2.2.2, “Set up databases” on page 30, please substitute thatname here.

40 Business Integration Solutions with MQSeries Integrator

Figure 28. Broker creation - Page 2 of 3

Finally, the complete command is summarized in the last window. ClickFinish to execute the actual command.

Figure 29. Broker creation - Page 3 of 3

Chapter 2. Installation and configuration 41

When the execution is finished, you should get the Command Successfulwindow:

Figure 30. Broker creation successful

2.2.6 Create a User Name ServerTo create a User Name Server, once more use the Command Assistant. TheCommand Assistant generates a command that can be executedindependently from a DOS window. Click:

Start -> Programs -> MQSeries Integrator Version 2.0 -> CommandAssistant -> Create User Name Server

or enter:

mqsicreateusernameserver -i userid -a password -q MQSI

Consistent with what we did before, we set the Windows NT service user IDto db2admin. The name of the queue manager is of course MQSI.

42 Business Integration Solutions with MQSeries Integrator

Figure 31. User Manager creation - Page 1 of 2

The second window gives you again the opportunity to review the command:

Figure 32. User Manager creation - Page 2 of 2

Chapter 2. Installation and configuration 43

After a while, the command prompts you with the Command Successfulwindow:

Figure 33. User Manager creation successful

The creation of all these MQSeries Integrator components has added anumber of Windows NT service tasks:

Figure 34. Windows NT Services overview

To summarize this unit, we’ve created three databases for the broker, theConfiguration Manager and the message repository. We’ve created a queuemanager called MQSI which is used by the broker, the Configuration Managerand the User Name Server. The broker was named MQSI, too, while theConfiguration Manager and the User Manager are not named.

2.3 Setting up the Control Center

Setting up the Control Center involves starting both the MQSeries Integratorservices and the Control Center, defining the user role(s) and registering(creating) a broker, and saving this work to a shared file.

44 Business Integration Solutions with MQSeries Integrator

2.3.1 Starting the MQSeries Integrator ServicesThe MQSeries Integrator Services can be started from the DOS commandprompt. The start commands are shown in the Command Successfulwindows displayed after creating the three components:

• Configuration Manager• Broker• User Name Server

The logical order of the three start commands is as follows:

1. Mqsistart UserNameServer

2. Mqsistart MQSI

3. Mqsistart ConfigMgr

The broker will use the User Name Server, which should therefore be startedbefore the broker. The Configuration Manager communicates with the brokerand therefore should be started after the broker. However, it is not necessaryto execute the commands in this order.

These services can also be started from the Windows NT Services GUIaccessed via the Control Panel folder. Configuring Windows NT toautomatically start the services when booting the operating system is wellworth doing. Check at the same time that the service IBM MQSeries is alsostarting automatically.

Figure 35. Starting the MQSeries Integrator services

Chapter 2. Installation and configuration 45

It is always worth checking the Event Viewer to make sure that no errors haveoccurred during initialization. Figure 36 shows the path to access the EventViewer and a sample window, showing the startup of the ConfigurationManager. Click Previous and Next to view adjacent tasks in the event log.Click:

Start -> Program -> Administrative Tools(Common) -> Event Viewer

Figure 36. Event Viewer message

Press Crtl+Alt+Del and select Task Manager -> Processes.

The Windows NT Task Manager Process view should show multiple amq*.exeprocesses for MQSeries and multiple bip*.exe processes belonging toMQSeries Integrator.

46 Business Integration Solutions with MQSeries Integrator

Figure 37. Windows NT Task Manager

2.3.2 Start the Control CenterTo start the Control Center, click Start -> Program -> MQSeries IntegratorVersion 2.0 -> Control Center.

The very first time that you launch the Control Center, you are presented withthe Connection dialog box, shown in Figure 38. In here, you should providethe details of the Queue Manager that is used by the Configuration Manager.

Chapter 2. Installation and configuration 47

Figure 38. Configuration Manager connection set-up

Host name: use the name of the computer where the Configuration Manageris running, in this exercise the local machine. This can always be found byusing the DOS hostname command:

D:\>hostname23-m1773

Port: enter the port the Configuration Server Queue Manager is listening on.In this example we are using the default port 1414, which was entered duringthe creation of the queue manager.

In a more complex environment, this could be a different MQSeries QueueManager from that used by the broker or User Name Server. In this exercisethe same MQSeries Queue Manager is used by all three services.

Queue Manager Name: MQSI was the name used when creating the queuemanager.

48 Business Integration Solutions with MQSeries Integrator

Figure 39. Main window Control Center

At this point an MQSeries server-connection channel is used to talk to theConfiguration Manager’s queue manager MQSI. The name of the channelobject is SYSTEM.BKR.CONFIG.

2.3.3 Adding the Log tabIt proves to be very useful to add the Log tab on the primary window byclicking File -> Log. The Log tab contains information related to thedeployment of message flows and other resources.

2.3.4 Set up user rolesUsers may choose (if authorized) which user role is required by clicking File-> Preferences. The role selected determines which tabs will be availablefrom the view. Optionally you may select All roles, which will show all eighttabs: the seven pertaining to user roles plus the Log tab.

Chapter 2. Installation and configuration 49

Figure 40. Setting your preferences in the Control Center

- Select User’s role. Check All roles (to allow a user to see all eighttabs). Click OK to finish.

50 Business Integration Solutions with MQSeries Integrator

Figure 41. Specifying your role

2.3.5 Register (create) a brokerIn this example the name of the broker is MQSI, as is that of our MQSeriesQueue Manager. This process essentially registers the broker to theConfiguration Manager.

An interesting point here is that you need to check out all resources that youwant to update via the Control Center. Basically, in a real-life environment,you can have multiple users using the Control Center at the same time tomanage the MQSeries Integrator environment or to develop new messageflows. It’s clear that a locking mechanism is needed to make sure that yourupdate is not overwritten by someone else.

1. Select the Topology tab

2. Right-click in the left pane Topology -> Check Out

3. Right-click Topology -> Create -> Broker

4. Provide the name of the broker: MQSI

5. Provide the Queue Manager name associated with the broker: MQSI

Chapter 2. Installation and configuration 51

Figure 42. Registering the existing broker

6. Click Finish to end the create task.

2.3.6 Save the workTo save the work, click File -> Local -> Save to shared. This will both checkin the new broker resource and save it locally in a file on the PC. The processwill prompt for a file name. In this example the file name mqsi.xml waschosen.

52 Business Integration Solutions with MQSeries Integrator

Figure 43. Topology view of the Control Center

The file mqsi.xml is the so-called workspace of the Control Center. It containsevery resource with which you have worked or which you have created.Resources that are created by someone else can be loaded into yourworkspace.

2.4 The "Hello world" message flow

In this section, we first create a simple message flow to explore the ControlCenter and to have a feeling of all the steps needed to deploy a messageflow. When you learn a new programming language, you will usually create a"Hello world" program that displays the "Hello world" string. Here, the "Helloworld" message flow will suffix any incoming message with the string "Helloworld".

Note that we will not explain all the options and possibilities at this time.

2.4.1 Building the message flowStart the Control Center and select the Message Flows tab. Right-clickMessage Flows in the left pane and select Create -> Message Flow. In thenext dialog box, provide a name for the message flow.

Chapter 2. Installation and configuration 53

Figure 44. Message flow creation

Explode the IBMPrimitives folder in the left pane. You get a list of all built-innodes. Drag-and-drop an MQInput node, a Compute node and an MQOutputnode to the Message Flow Definition pane.

54 Business Integration Solutions with MQSeries Integrator

Figure 45. Message flow overview

Each node can have input and output terminals. By connecting the outputterminal of one node to the input node of another node, you build upstep-by-step a complete message flow. Some nodes do require someconfiguration on their own. Right-click the MQInput node and selectProperties:

Chapter 2. Installation and configuration 55

Figure 46. MQInput node properties

The MQInput node encapsulates an MQSeries MQGET call. It providesparameters that will be used to execute the MQGET call. Select the Basic taband provide the name of a queue from which the broker will read inputmessages.

Figure 47. MQInput node configuration

Press the OK button to close the dialog box.

Right-click the MQOutput node and select Properties. The MQOutput nodeencapsulates an MQSeries MQPUT call. Via the different tabs you cancontrol how the MQPUT will be executed. Select the Basic tab and fill in thename of the queue onto which the broker will write the transformed message.

56 Business Integration Solutions with MQSeries Integrator

Figure 48. MQOutput node configuration

Click the OK button to close the dialog box.

Right-click the Compute node and select Properties. The Compute nodeprovides the possibility to transform messages. In the next chapters this nodewill be investigated more deeply. Here in this example we use only somebasic features.

Chapter 2. Installation and configuration 57

Figure 49. Compute node properties

Check Copy Entire Message and select the ESQL tab. The ESQL line

SET OutputRoot = InputRoot;

is generated as a consequence of checking the option Copy EntireMessage. This statement means that the whole input message will be copiedto the output message, including message headers.

Add a second ESQL line to add a new field to the XML stream, as shown inFigure 50.

58 Business Integration Solutions with MQSeries Integrator

Figure 50. Compute node: ESQL statements

This second ESQL statement assigns the value "Hello world!" to the XMLelement MQSIOutput. Because this element did not yet exist, it will beappended as the last element in the new message. Click the OK button toclose the dialog box.

Next step is to wire the three nodes together. Right-click the MQInput nodeand select Connect->Out. A solid line should appear. Move the cursor overthe input terminal of the Compute node and press the left mouse button toconnect the solid line with it. Right-click the Compute node and selectConnect->Out. Move the cursor over the input terminal of the MQOutputnode and click the left mouse button. You should now see something likeFigure 51:

Chapter 2. Installation and configuration 59

Figure 51. Completed message flow

Save your work up till now by selecting File -> Local -> Save to Shared.

2.4.2 Deploying the HelloWorld message flowAt this point a message flow has been defined. But now you need to assignthe message flow to one or more brokers. Message flows are organized inexecution groups. You can think of an execution group as the collection ofmessage flows belonging to the same application. For this example we usethe pre-defined execution group called default. Select the Assignments tabof the Control Center and open the Message Flows folder in the DeployableMessage Type pane (the middle pane). Our little HelloWorld flow shouldappear:

60 Business Integration Solutions with MQSeries Integrator

Figure 52. Broker Assignment overview

At this point, you are going to update resources that could be updated byothers too. Thus, you need to make sure that you lock them. In the left pane(Domain Hierarchy) right-click the default execution group and select CheckOut. Drag the HelloWorld message flow from the middle pane and drop it intothe box of the default execution group in the right pane (the Domain Topologypane).

Chapter 2. Installation and configuration 61

Figure 53. Assigning the message flow

You have now configured your broker to use the HelloWorld message flow.Save your work by selecting File->Local->Save to Shared.

The next step is to deploy this message flow to your running broker.Right-click your broker in the left pane and select Deploy -> CompleteAssignments Configuration. This will launch a background process toupdate all resources. The successful initiation of this process is indicated bythe message box shown in Figure 54.

62 Business Integration Solutions with MQSeries Integrator

Figure 54. Deployment is initiated successfully

It should be stressed that the successful initiation of the deployment is not aguarantee that the deployment itself is successful. Depending on thecomplexity of the message flow - and the capacity of your machine - thedeployment can take a while. To verify the successful deployment go to theLog tab of your Control Center and refresh the log (Log -> Refresh Log). Ifthe deployment was successful, your Control Center Log page should looklike Figure 55.

Chapter 2. Installation and configuration 63

Figure 55. Log messages indicating the deployment of a message flow

2.4.3 Testing the message flowBefore we can actually test the message flow, we need to define theMQSeries queues that were used in the message flow. You can do this eitherusing the MQSeries Explorer or the text-based tool runmqsc.

64 Business Integration Solutions with MQSeries Integrator

Figure 56. runmqsc session to define the queues

After you have defined the queues, you can verify that your broker is usingyour message flow. The value for IPPROCS for queueHELLO_WORLD.INPUT is at 1, meaning that someone has opened thequeue to read messages.

Figure 57. Checking that the broker is using the queue

Chapter 2. Installation and configuration 65

To test the message flow, we will use the always very useful programsamqsput and amqsget, which are sample programs delivered with MQSeries.Create a text file helloworld.txt with a simple XML message:

<Message>this is my input</Message>

Run amqsput and amqsget to verify the results shown in Figure 58.

Figure 58. Testing the message flow

The message retrieved by amqsget has been handled by the broker and theXML message now contains a second field called MQSIOutput with a value"Hello world!".

Another way of testing the message flow is by using the MQSeries Explorerinterface. You can use the Put test message option and the Browse option onthe input and output queues. In this case you are not limited by the shortbuffer in the amqsget program.

2.5 Summary

At this stage, you should now have a running MQSeries Integratorenvironment with a simple message flow in "production". This chapter shouldhave given you a feeling about the Control Center and its functionality. Thenext chapters will explore more deeply the possibilities and options.

66 Business Integration Solutions with MQSeries Integrator

Chapter 3. Introduction to XML

In the previous chapter we saw a few occasions where XML was used inMQSeries Integrator. The workspace is saved in an XML format and in theHelloWorld message flow we saw how easy it was to work with XMLmessages and how we could enhance those messages. The next chapterswill contain some more examples of using XML in MQSeries Integrator.

Because of the importance of XML to MQSeries Integrator, and MQSeries ingeneral, we decided to include an introduction chapter to XML. This chapteris not intended to reveal all the secrets of XML. Its intention is merely toexplain some of the concepts and terminology in the XML world and toexplain why XML is so important for today’s Information Technologyprofessionals.

3.1 XML concepts and terminology

While many readers may know something about XML, let’s start by providingan example of XML:

Figure 59. Sample XML code

The above stream of characters could be the representation of a customerservice report that was entered by Mr. Smith to complain about hisundelivered order. Mr. Smith has probably entered this data on a nicelyformatted Web page and clicked the Send button. To get this information into

Message><CustomerName><First>William</First><Last>Smith</Last>

</CustomerName><Complaint><Type>Order</Type><Reference>XYZ123ABC</Reference><Text>

I placed an order on 11-15-99, well in time for Christmas and I tinot had a delivery schedule sent to me.Please cancel the order and refund me NOW.</Text>

</Complaint></Message>

© Copyright IBM Corp. 2000 67

the customer service system of this retailer, three important and relatedInternet technologies are used.

• Hyper Text Markup Language (HTML)

• HyperText Transport Protocol (HTTP)

• eXtensible Markup Language (XML)

HTML is the language that is used to express the way data is presented in thebrowser, while HTTP is the transport protocol to get the data from the Webbrowser to the computer systems of the retailer. XML is the language toexpress the data itself.

For those of you who are familiar with HTML, it is clear that XML has much incommon with HTML. Actually, both languages have a common ancestor:SGML or Standard Generalized Markup Language. SGML’s history goes backto the late 1960s and is the work of an IBM employee who was developing asystem to share documents. SGML is the evolution of that work and itbecame an ISO standard in the mid-1980s.

HTML is defined using SGML and is a limited subset of SGML, mainlyintended to express the presentation of data in a browser. HTML provides afixed set of tags, which are keywords surrounded by angled brackets.Because the set of tags is fixed, it becomes difficult to express all differenttypes of data than one can imagine and that are available on the Internet.XML provides the solution here. Because it is extensible, designers of XMLdocuments can add tags that are relevant for their application area. One caneasily imagine an XML implementation for the banking industry. Such animplementation would include such tags as <account_number> or<account_balance>.

Given the fact that the tag set of XML is extensible, you could definespecialized tag sets for specific industries and applications to be used forexchanging data between those applications. Applications can store theirdocuments in a super set of their industry’s standard without losingcompatibility with the original format. And because XML documents are textbased, they can be distributed easily over the Internet. XML documents arereadable; thus with a simple text editor you can already edit them. Finally, animmediate advantage of XML is the availability of standard XML parsers thatmake it easy for an application to write and read XML documents.

Essentially, an XML document consists of a nested hierarchy of elementsstarting with the outermost root element, which is <Message> in our example.Each element starts with a start tag and must have a corresponding end tag

68 Business Integration Solutions with MQSeries Integrator

with a prefixed forward slash. An element itself can have attributes, which is alist of name=”value” pairs.

3.1.1 More terminologyGoing back to the XML stream shown in Figure 59 on page 67, let’s have acloser look at the data. Consider the following part:

<CustomerName><First>William/First><Last>Smith</Last>

</CustomerName>

This piece of data tells us that William Smith is the name of a customer.However, it does not tell us something about the context in which this is valid.Is it the name of a customer of a bank? A book store? The exact meaning willbe given by the application that reads and interprets the data. Without havingany knowledge of the application in which this XML document is used, we canonly tell that it is well-formed, which means that there are no irregularities inthe document. When a start tag (such as <CustomerName>) is found in thedocument, an end tag must be present as well. Also, an XML document mustnot contain unclosed tags.

To parse an XML message, its well-formedness is sufficient. The parser doesnot need to know the meaning of the tags to determine that <CustomerName>is a top-level element with two inner elements <First> and <Last> and thatWilliam and Smith are the values of these elements. Referring to theHelloWorld message flow in the previous chapter, the XML parser built inMQSeries Integrator had no idea about the meaning of the tags in our inputmessage. However, the parser was able to parse the XML message becauseit was well-formed.

But, wouldn’t it be nice if the XML parser can also validate the values for eachfield or check that all needed elements are there? It’s at this point thatDocument Type Definitions (DTDs) play a role. A DTD specifies thegrammatical structure of an XML document. Consider the XML example inFigure 59 on page 67. A DTD can instruct the parser that it needs to checkthat the Complaint Type has a valid value: Order or Delivery. It can alsospecify that an element is optional. The Text attribute for example could beoptional.

To use a DTD, you have two options. You can include the DTD in the XMLstream itself:

<?xml version=”1.0”?><!DOCTYPE Message [ ...

Chapter 3. Introduction to XML 69

]>

Or, you can refer to an external file that contains the DTD:

<?xml version=”1.0”><!DOCTYPE Message SYSTEM “Message.dtd”><Message>...</Message>

The two most important things you will find in a DTD are element declarationsand attribute list declarations. Element declarations specify which tags can beused in a document, their relationship, and what type of data you can expectin that element. Attribute list declarations identify which attributes can beassociated with each element type. A DTD also specifies if an element isoptional or compulsory, if it can appear more than once, and so on.

A possible DTD for the sample XML document could look like this. The * afterComplaint indicates that this document type can contain zero or morecomplaints. The question mark next to Text indicates that this is an optionalelement. #PCDATA is the keyword to be used to express a string data type.

<!DOCTYPE Message [<!ELEMENT Message (CustomerName, Complaint*)><!ELEMENT CustomerName (First, Last)><!ELEMENT First (#PCDATA)><!ELEMENT Last (#PCDATA)><!ELEMENT Complaint (Type, Reference, Text?)><!ELEMENT Type (#PCDATA)><!ELEMENT Reference (#PCDATA)><!ELEMENT Text (#PCDATA)>]>

3.2 The importance of XML

When we think about applications, the major points to consider are how theyhandle the following:

1. data storage

2. data sharing

3. data transformation

XML can be used to store data. The availability of standard parsers makes iteasy to read and write data in an XML format which speeds up developmenttime. Another advantage is that the format to store the data is an open format,

70 Business Integration Solutions with MQSeries Integrator

instead of a proprietary format. Given that your data storage is now based onopen standards, the same format can be used to share the data with differentsystems. This allows for easier integration. You no longer need proprietaryimport/export functions to allow sharing your data with other applications.Even if the application continues to store its data in a proprietary format (thinkabout database servers), XML is still appealing as the standard format forexporting and importing data to and from other sources. These other sourcescan be computer systems within an enterprise or the systems for yourbusiness partners. The ability to link computer systems together is a keyfocus in many industries and XML can help here, given its open nature. Thus,XML is also the language for data transmission.

3.2.1 Importance for the MQSeries FamilyGiven the above examples of possible uses of XML, the importance of XML toMQSeries is immediately clear. The sharing and transmission of databetween different computer systems is exactly the key mission of the baseMQSeries product. MQSeries allows you to distribute data across more than35 different platforms with assured delivery. The publish/subscribe extensionmakes it possible to share data with as many applications as you like. Thepublisher (source of information) has no link with the subscriber (theconsumer) of that information. MQSeries makes sure that the right dataarrives at the right place, independent of platform, network protocol, or theavailability of systems. The nice thing is that nothing needs to be done tohave MQSeries work with XML messages. For MQSeries, an XML-formattedmessage is just another message.

But that’s not the end for the MQSeries family. Although the acceptance ofXML is growing fast, you will still have much data in proprietary formats for along time. Nobody will change a key application in his enterprise just to makeuse of XML. And even if you would have the resources, there are situationswhere you are not in control of the behavior of an application. Think about allthe packaged applications with their private import/export facilities. For allthese types of data, you can work with MQSeries Integrator to transform thedata into XML messages before delivering the data to XML-enabledapplications, or vice-versa, transforming the XML messages into theproprietary formats.

Even between XML-enabled applications, MQSeries Integrator can play a keyrole. Like any technology, XML will evolve. Industry-specific XML languageswill exist that are not compatible. And over time, a specific industry mighthave a number of different versions of its XML standard. Again MQSeriesIntegrator can help you to transform the data into the correct format.

Chapter 3. Introduction to XML 71

Finally you can easily imagine an application that generates huge XMLstreams while the consumer of the data is only interested in part of the data.MQSeries Integrator can work here to filter out the necessary elements.

3.2.2 Use of XML within MQSeries IntegratorGiven all the advantages of XML that we have shown earlier, it comes as nosurprise that MQSeries Integrator itself is heavily using XML technology. Wesaw already that the Control Center of MQSeries Integrator is storing andsharing its data in an XML format. When you export or import message setsfrom your Configuration Manager, it is again stored in an XML format.

When externalizing data for system management products, MQSeriesIntegrator generates event messages in an XML format. One can imagine thatin the near future this style of event messages will be used for the baseMQSeries product instead of the current, proprietary PCF format.

Another form of data externalization is the user trace. The user trace is a veryhelpful component of MQSeries Integrator for a developer and tester ofmessage flows. Because the data is internally managed in an XML format, itwas the clear choice to use this format again for tracing purposes. Note,however, that a tool is available in MQSeries Integrator to reformat theXML-formatted user trace in a conventional text file. Thus, if you have noimmediate access to an XML-capable viewer, such as Microsoft’s InternetExplorer, you’re still able to make use of the tracing facility.

We’ve already mentioned that a user can build nodes themselves for specificpurposes. The way to configure MQSeries Integrator to use thesecustomer-built nodes is again using XML-formatted configuration files.

While the above list is absolutely not intended to be a complete list, it isalready clear that XML technology is a core part of MQSeries Integrator andthat its use can only grow over time in the MQSeries Family.

72 Business Integration Solutions with MQSeries Integrator

Chapter 4. Advanced setup of MQSeries Integrator

In this chapter we present a more sophisticated setup with multiple brokers,using MQSeries clustering features and separating database functionality ondifferent machines.

4.1 Using a remote database for the Configuration Manager

The configuration manager uses two sets of tables. One set is used for themessage repository, while the other set is used to store all other configurationinformation, including the message flows, the broker topology and theassignment of message flows. This information is more or less static in aproduction environment.

The set of tables used by a broker holds state information and informationneeded at run time. Thus, it is a good idea for performance reasons to makethe broker’s set of tables available on the same system where the brokerruns.

While the set of tables for a broker are accessed only by the broker itself, thetables associated with the Configuration Manager can be accessed by manyusers of the Control Center at the same time. To manage multiple concurrentusers it is good idea to locate the tables on a dedicated database server. Inthe next sections we describe the steps necessary to create the database onan AIX server for use by the Configuration Manager.

4.1.1 Preparing the AIX systemWe need to define a user ID on the AIX machine to be used by theConfiguration Manager when accessing the databases. We defined a user IDmqsi with no special authority. To create a user ID, you use the smitty tool orthe adduser command.

We also need to define the databases. Log on with dbadmin authority andstart the DB2 command line processor. Create two databases with thefollowing commands:

CREATE DATABASE MQSICFGCREATE DATABASE MQSIMRM

To set the necessary access rights for the mqsi user, execute a SQL GRANTcommand as follows:

© Copyright IBM Corp. 2000 73

CONNECT TO MQSICFGGRANT CREATETAB, BINDADD, CONNECT, CREATE_NOT_FENCED,IMPLIT_SCHEMA ON DATABASE TO USER mqsiCONNECT TO MQSIMRMGRANT CREATETAB, BINDADD, CONNECT, CREATE_NOT_FENCED,IMPLIT_SCHEMA ON DATABASE TO USER mqsi

End the DB2 session using the quit command.

4.1.2 Configuring DB2 Client accessOn the NT machine that will host the Configuration Manager, start the DB2Client Configuration Assistant to get access to the AIX databases. From themain window, click the Add button. On the first tab of the ConfigurationAssistant, select the option Manually configure a connection. SelectTCP/IP as the communication protocol and provide the host name and portnumber on the next tab. One way to find the port number for your DB2instance is to look it up in the /etc/services file on AIX. However, yourdatabase administrator should be able to give you the information.

On the next tab, provide the name of the database (MQSICFG). Finally, makesure that the database is registered for ODBC as a system data source. Clickthe Done button and select the possibility to test the connection. Use themqsi user ID to connect to the database.

Repeat the same process for the MQSIMRM database.

4.2 Creating a multi-broker domain

In this section we will use the Configuration Manager created in the previoussection and build a broker domain with brokers running on multiple systems.We use the MQSeries clustering feature to reduce the number of objects todefine and to create a workload balancing MQSI environment.

The final setup consists of:

1. A Windows NT machine, called CFG here, to host the ConfigurationManager and its queue manager MQSI_CONFIG_QMGR.

2. An ODBC connection from CFG to the AIX machine that hosts theConfiguration Manager’s database.

3. A Windows NT machine, called USR below, to host the User Name Serverand its queue manager MQSI_USER_QMGR.

74 Business Integration Solutions with MQSeries Integrator

4. Three Windows NT machines, called BRK1, BRK2 and BRK3, to hostthree MQSeries Integrator brokers and their associated queue managers.

5. Two Windows NT machines that act as message generator and messageconsumer. Between message generation and message consumption, themessage will go through one of the brokers.

See Figure 60 for an overview of the configuration.

Figure 60. Multi-broker setup using MQSeries clustering

MQSI_CONSUMER

MESSAGECONSUMER

MQSI_PRODUCER

MESSAGEPRODUCER

MQSI_USER_QMGR

USR

MQSI_BROKER_1MQSI_QMGR_1

BRK1

Workload Balanced MQSeries Cluster Channel

MQSeries Cluster Channel

CFG

CONFIGURATIONMANAGER

MQSI-CONFIG-QMGR

AIX

DB2 MQSI CFGMQSI MRM

BRK2

MQSI_BROKER_2MQSI_QMGR_2

BRK3

MQSI_BROKER_3MQSI_QMGR_3

Chapter 4. Advanced setup of MQSeries Integrator 75

With this setup we want to demonstrate how to build a multi-broker domainthat uses MQSeries clustering to get a workload balanced environment.

4.2.1 Overview of the MQSeries clustering featureThe MQSeries clustering feature has been introduced with Version 5.1 ofMQSeries on Intel and UNIX platforms and with Version 2.1 on OS/390.Basically, clustering is a new way to connect queue managers to each other.In traditional MQSeries distributed queuing, one had to define a transmissionqueue and a pair of sender/receiver channels to enable communicationbetween two queue managers. In an environment with many (hundreds orthousands) queue managers, it is a big task to define all those objects.

Let’s assume you have a number of n queue managers that need to talk toeach other. In traditional MQSeries distributed queuing, you need to definen-1 transmission queues, n-1 sender channels and n-1 receiver channels oneach queue manager. On top of this, you may need remote queue definitionsfor each local queue to which you want to send messages. For n systems, youneed at least 3*n*(n-1) definitions to have full point-to-point communication.

In a cluster environment you should promote one (or ideally two) queuemanagers as full repository queue managers. This means that such a queuemanager knows all other queue managers in the cluster. It knows whatclustered objects (local queues or any other type of object) are hosted bywhich queue manager and it knows how to reach those queue managers.This last thing means that the full repository queue manager has a templatedefinition of a sender and receiver channel definition that can be used tocreate automatically a new sender/receiver channel when needed.

To make two queue managers QM1 and QM2 a full repository queuemanager for a cluster named MY_CLUSTER, you need to execute thefollowing MQSeries commands.

On QM1:

DEFINE CLUSCHL(TO.QM1) CHLTYPE(CLUSRCVR) +CONNAME(hostname1) +CLUSTER(MY_CLUSTER)

DEFINE CLUSCHL(TO.QM2) CHLTYPE(CLUSSDR) +CONNAME(hostname2) +CLUSTER(MY_CLUSTER)

ALTER QMGR REPOS(MY_CLUSTER)

76 Business Integration Solutions with MQSeries Integrator

On QM2:

DEFINE CLUSCHL(TO.QM2) CHLTYPE(CLUSRCVR) +CONNAME(hostname2) +TRPTYPE(TCP) +CLUSTER(MY_CLUSTER)

DEFINE CLUSCHL(TO.QM1) CHLTYPE(CLUSSDR) +CONNAME(hostname1) +TRPTYPE(TCP) +CLUSTER(MY_CLUSTER)

ALTER QMGR REPOS(MY_CLUSTER)

The object of type CLUSRCVR, or cluster receiver, specifies how a queuemanager wants other queue managers to talk to him, or more technically, howother queue managers should create a sender channel to send messages tothis queue manager.

The object of type CLUSSDR, or cluster sender, should provide the queuemanager a sender channel to the other full repository queue manager in thecluster.

The ALTER QMGR command finally makes the queue manager a full repositoryqueue manager.

As soon as these definitions are in place, you will have two-waycommunication between QM1 and QM2. When you now add a local queue toQM1 and you specify the cluster name MY_CLUSTER, QM1 will pass thedefinition of that object to the second full repository queue manager QM2.

DEFINE QLOCAL(CLUSTERED_QUEUE) CLUSTER(MY_CLUSTER)

Given that QM2 has channels to QM1 and that QM2 now knows that thequeue CLUSTERED_QUEUE exists on QM1, you do not need to define a remotequeue object! Note that we haven’t defined transmission queues so far.MQSeries cluster channels are using a common, predefined transmissionqueue called SYSTEM.CLUSTER.TRANSMIT.QUEUE.

The real benefit of MQSeries clusters becomes clear when adding additionalqueue managers to the cluster. To add QM3 to the cluster, one needs todefine a cluster receiver channel to make clear to the cluster how other queuemanagers should talk to QM3:

Chapter 4. Advanced setup of MQSeries Integrator 77

DEFINE CLUSCHL(TO.QM3) CHLTYPE(CLUSRCVR) +CONNAME(hostname3) +TRPTYPE(TCP) +CLUSTER(MY_CLUSTER)

The next and last thing you need to make QM3 part of the cluster is a clustersender channel to one full repository queue manager. Because there are twofull repository queue managers, you can choose. Which one you select is notimportant.

DEFINE CLUSCHL(TO.QM2) CHLTYPE(CLUSSDR) +CONNAME(hostname2) +TRPTYPE(TCP) +CLUSTER(MY_CLUSTER)

When this object is created, QM3 will start the channel TO.QM2 and giveQM2 the definition of the channel TO.QM3. QM2 will immediately use thatdefinition to create a sender channel from QM2 to QM3. From this point onQM3 can use any object in the cluster MY_CLUSTER! When an applicationconnects to QM3 and opens the queue CLUSTERED_QUEUE, QM3 will not knowwhere that object lives. At least QM3 knows that it is not hosting this objectitself. Thus, it asks its full repository queue manager QM2 about this object.QM2 replies with the definition: CLUSTERED_QUEUE is a local queue hosted byQM1. Because QM3 does not know how to talk to QM1, QM2 sends anotherrequest to QM2 to get the communication parameters of QM1. Now, QM2replies with the cluster receiver channel definition that QM3 uses to createautomatically a sender channel from QM3 to QM1. At this point, QM3 is ableto send messages to QM1 without any manual definition.

The next big advantage of clustering is the possibilities for workloadbalancing and take-over. Assume that we have a local queue WORKLOADhosted on QM1 and QM2. The queue is defined into the cluster. When anapplication connects to QM3 and opens the queue WORKLOAD, QM3 can nowchoose to which queue manager it will send messages. QM3 will select thatqueue manager to which it was able to set up communication. If channelTO.QM1 has gone into retry and TO.QM2 is running, QM3 will choose to sendmessages to QM2. If both channels are active, QM3 will send the messagesto both queue managers on a round-robin basis, if the application oradministrator has allowed this. The MQOPEN now has a new option to controlthe spreading of workload. If you want to choose the destination at MQOPENtime, you specify the option MQOO_BIND_AT_OPEN. If you want to spreadthe workload over the active systems, you need to use the optionMQOO_BIND_NOT_FIXED. By using one of these options, an application can

78 Business Integration Solutions with MQSeries Integrator

control if all messages generated between MQOPEN and MQCLOSE aresent to one system or to each system that hosts the target queue.

While the above is definitely not a full coverage of MQSeries clustering, wehope that you now have some basic understanding of this feature and how itcan help the MQSeries administrator to create a more powerful and reliableMQSeries network with fewer definitions. For more information on this topic,please refer to the MQSeries product manual MQSeries: Queue ManagerClusters, SC34-5349, and the redbook MQSeries Version 5.1 Administrationand Programming Examples, SG24-5849.

4.2.2 Creating the MQSeries Integrator ClusterWe start with the creation of two queue managers to be used by theConfiguration Manager and the User Name Server. These queue managerswill be the full repository managers of the cluster.

On machine CFG, create the queue manager with the command:

crtmqm -u SYSTEM.DEAD.LETTER.QUEUE MQSI_CONFIG_QMGR

On machine USR, create the queue manager with the command:

crtmqm -u SYSTEM.DEAD.LETTER.QUEUE MQSI_USER_QMGR

Start the MQSeries Explorer on machine CFG to create the cluster channelobjects. In the MQSI_CONFIG_QMGR folder, right-click the Channelsub-folder and select New -> Cluster Receiver Channel. Name the objectTO.MQSI_CONFIG_QMGR and provide the communication parameters as shownin Figure 61.

Chapter 4. Advanced setup of MQSeries Integrator 79

Figure 61. Defining a cluster receiver channel - part 1

Click the Cluster tab to specify the name of the cluster: MQSI_CLUSTER.

Figure 62. Defining a cluster receiver channel - part 2

80 Business Integration Solutions with MQSeries Integrator

Use the same method to define the cluster receiver channelTO.MQSI_USER_QMGR on machine USR for queue managerMQSI_USER_QMGR. Please note that you get a warning message in theEvent Viewer that says that you do not have yet a full repository queuemanager for the cluster MQSI_CLUSTER. You can ignore this message becausewe’re still building up the definitions. But the Event Viewer gives you exactlywhat you need to do in the next step.

Figure 63. Event Viewer warning message

To make both queue managers a full repository, right-click on their name inthe MQSeries Explorer and select Properties. Select the Repository tab andcheck Repository for a cluster and fill in the value MQSI_CLUSTER in the entryfield. Perform this change for both queue managers on machines CFG andUSR.

Chapter 4. Advanced setup of MQSeries Integrator 81

Figure 64. Promoting the queue manager to a full repository queue manager

The next step is to interconnect both full repository queue managers bycreating a sender channel on both queue managers pointing to the otherqueue manager.

In MQSeries Explorer, right-click on the Channels folder for queue managerMQSI_CONFIG_QMGR and select New -> Cluster Sender Channel. Namethe object TO.MQSI_USER_QMGR and provide the communicationparameters.

82 Business Integration Solutions with MQSeries Integrator

Figure 65. Defining a cluster sender channel- part 1

Click the Cluster tab and make the object shared in cluster MQSI_CLUSTER:

Figure 66. Defining a cluster sender channel - part 2

Chapter 4. Advanced setup of MQSeries Integrator 83

At this point the queue manager MQSI_CONFIG_QMGR will set upcommunication with MQSI_USER_QMGR and pass it all information aboutclustered objects. Repeat now the same steps to create cluster senderchannel TO.MQSI_CONFIG_QMGR on queue manager MQSI_USER_QMGR tocomplete the setup of the two full repository queue managers.

The next step is to define the queue managers for the brokers and to makethem part of the cluster. On the first broker machine, execute the command:

crtmqm -u SYSTEM.DEAD.LETTER.QUEUE MQSI_QMGR_1

Repeat this command on the two other Windows NT boxes for the queuemanagers MQSI_QMGR_2 and MQSI_QMGR_2.

To make queue manager MQSI_QMGR_1 part of the cluster, execute thefollowing commands in a runmqsc session:

DEFINE CLUSCHL(TO.MQSI_QMGR_1) CHLTYPE(CLUSRCVR) +CONNAME(m238p4xl) +TRPTYPE(TCP) +CLUSTER(MQSI_CLUSTER)

DEFINE CLUSCHL(TO.MQSI_CONFIG_QMGR) CHLTYPE(CLUSSDR) +CONNAME(97-94F46) +TRPTYPE(TCP) +CLUSTER(MQSI_CLUSTER)

For MQSI_QMGR_2 the commands are:

DEFINE CLUSCHL(TO.MQSI_QMGR_2) CHLTYPE(CLUSRCVR) +CONNAME(m238p4yp) +TRPTYPE(TCP) +CLUSTER(MQSI_CLUSTER)

DEFINE CLUSCHL(TO.MQSI_USER_QMGR) CHLTYPE(CLUSSDR) +CONNAME(97-94F46) +TRPTYPE(TCP) +CLUSTER(MQSI_CLUSTER)

For MQSI_QMGR_3 the commands are:

DEFINE CLUSCHL(TO.MQSI_QMGR_3) CHLTYPE(CLUSRCVR) +CONNAME(m238p4ta) +TRPTYPE(TCP) +CLUSTER(MQSI_CLUSTER)

DEFINE CLUSCHL(TO.MQSI_CONFIG_QMGR) CHLTYPE(CLUSSDR) +

84 Business Integration Solutions with MQSeries Integrator

CONNAME(97-94F46) +TRPTYPE(TCP) +CLUSTER(MQSI_CLUSTER)

At this point all MQSeries resources are defined to have a fully operationalcluster to be used by the different MQSeries Integrator components. We cannow define the Configuration Manager, the User Name Server and the threebrokers to complete the multi-broker domain.

4.2.3 Creating the Configuration ManagerTo create the Configuration Manager, we again use the Command Assistant.Provide the necessary parameters as shown below:

Figure 67. Create Configuration Manager window

Note that the creation of the Configuration Manager can take some more timenow because the database is defined remotely.

Start the Configuration Manager from the command line using the command:

Chapter 4. Advanced setup of MQSeries Integrator 85

mqsistart ConfigMgr

Alternatively, use the Services applet in the Control Panel to start thiscomponent.

4.2.4 Creating the User Name ServerThe creation of the User Name Server is no different from what we did beforein 2.2.6, “Create a User Name Server” on page 42. Use the CommandAssistant to provide the necessary parameters:

Figure 68. Create a User Name Server

Start the User Name Server with the command:

mqsistart UserNameServer

or use the Services applet in the Control Panel.

4.2.5 Creating the brokersNow that we’ve created the User Name Server and the ConfigurationManager, we’re ready to create the three brokers. On each Windows NTmachine we need a user ID for the broker. Use Windows NT’s User Manager

86 Business Integration Solutions with MQSeries Integrator

to add a new user ID mqsibrk1 and add it to the NT user groups mqm andmqbrkrs. Make sure that the password does not expire.

The next step is the creation of the broker’s database. Start DB2’s CommandLine Processor and execute the command:

CREATE DATABASE MQSIBRK1

Start the DB2 Client Configuration Assistant to register the database forODBC. Finally grant access for user mqsibrk1 to the database. You can usethe DB2 Control Center or again DB2’s Command Line Processor. From theDB2 Control Center, right-click the MQSIBRK1 database and selectAuthorities. Click the Add User button and select mqsibrk1 from the list.Set all authorities to Yes except for the DBADMIN authority.

Figure 69. Authority settings for user mqsibrk1

If you prefer to use DB2’s Command Line Processor, the equivalent SQLGRANT command is shown in Figure 70.

Chapter 4. Advanced setup of MQSeries Integrator 87

Figure 70. SQL GRANT command for user mqsibrk1

Now, all elements are defined and we’re ready to create the broker. UseMQSeries Integrator’s Command Assistant to specify the necessaryattributes.

The broker’s name is MQSI_BROKER_1. Its service user ID was mqsibrk1and the queue manager is named MQSI_QMGR_1.

Figure 71. Create Broker - part 1

88 Business Integration Solutions with MQSeries Integrator

The database is MQSIBRK1 and the user ID to use for database access isagain mqsibrk1.

Figure 72. Create Broker - part 2

Click the Next button to go to the third page and review all parameters beforeclicking the Finish button.

Repeat all these steps for the brokers MQSI_BROKER_2 andMQSI_BROKER_3. The user IDs to define are mqsibrk2 and mqsibrk3. Thename of the broker’s database is MQSIBRK2 and MQSIBRK3. The names ofthe queue managers were MQSI_QMGR_2 and MQSI_QMGR_3.

Finally, start all brokers on the different systems using the command

mqsistart MQSI_BROKER_x

where x is 1, 2 or 3. You can also start the broker using the Services applet inthe Control Panel.

4.2.6 Using the Control Center to link everything togetherBefore starting MQSeries Integrator’s Control Center, it might be a good ideato check that all components are running fine. A first place to look for statusmessages is the Event Viewer. Make sure that there are no warning or error

Chapter 4. Advanced setup of MQSeries Integrator 89

messages from sources MQSeries or MQSeriesIntegrator2. If you shouldhave any, read them carefully and resolve the error. You could also useMQSeries Explorer to verify that all queue managers are up and running andthat all five queue managers are part of the cluster.

When you have checked that all components are active, you’re ready tolaunch the MQSeries Integrator Control Center. You can start it from anymachine in the network, as long as it is possible to create an MQSeries JavaClient connection to the queue manager of your Configuration Manager. Ifyou have used the Control Center before, check that you are connected to thecorrect Configuration Manager. Select File -> Connection to verify theMQSeries Java Client connection options. Because the Control Center is nowconnected to a brand new Configuration Manager, it is also a good idea tostart with a new workspace (File -> New Workspace) to avoid confusion. Ifyou had used the Control Center before, it will try to use the previousMQSeries Java Client connection options. If those options are not valid(you’ve deleted that queue manager, or it is not active), you will time out andhave the opportunity to enter the correct MQSeries Java Client connectionoptions.

Similarly to what we’ve done in 2.3.5, “Register (create) a broker” on page 51,we need to add the brokers to the topology. Go to the Topology tab of theControl Center and check out the Topology document. Right-click theTopology document and select Create -> Broker to add the brokerMQSI_BROKER_1 with queue manager MQSI_QMGR_1. Repeat theprocedure for the brokers MQSI_BROKER_2 and MQSI_BROKER_3 withqueue manager MQSI_QMGR_2 and MQSI_QMGR_3. Check in the Topologydocument and deploy the complete topology by right-clicking the Topologydocument and selecting Deploy -> Complete Topology. Switch to the Logtab of the Control Center and verify that all three brokers have replied toreport the successful update of their runtime configuration. Depending on thecapacity of your systems, this could take a minute or so. If one or more repliesare missing, use MQSeries Explorer to find out which channels have notstarted. You can also use the Event Viewer to find out why reports aremissing. In MQSeries Explorer, select the Cluster Queue Managers folderfor queue manager MQSI_CONFIG_QMGR. The channel status for the threebroker queue managers should be running. If it isn’t, the configurationmessage has not reached the broker yet. Verify your MQSeries setup on bothsides to find the reason for the failure.

90 Business Integration Solutions with MQSeries Integrator

Figure 73. MQSeries Explorer: status of the cluster queue managers

If all queue managers report a running status, double-click theMQSI_CONFIG_QMGR entry to check the status of the receiver channels.The window should have three entries with a Channel Status Type of Currentand a Channel Status of Running, as shown in Figure 74.

Chapter 4. Advanced setup of MQSeries Integrator 91

Figure 74. MQSeries Explorer: status of the cluster receiver channels

If one or more entries are missing, check the MQSeries configuration anderror logs on both sides to find out what went wrong.

When you’ve sorted out any configuration errors, you have a fully functionalmulti-broker domain.

4.3 A multi-broker domain in action

We now have a fully operational multi-broker domain. It’s time to connectsome applications to this domain. Our setup consists of a message-producingqueue manager, MQSI_PRODUCER, and a message-consuming queuemanager, MQSI_CONSUMER. To create these queue managers and toconnect them to the cluster, we use basically the same techniques asdiscussed before.

4.3.1 Connecting the application queue managersFor both queue managers we created a cluster sender channelTO.MQSI_USER_QMGR, which is one of the full repository queue managers.With the definition of a cluster receiver channel for each of these two queuemanagers, the setup is complete and they are now part of the cluster.

92 Business Integration Solutions with MQSeries Integrator

The message flow that we want to use in this scenario is the simpleHelloWorld message flow that was created in 2.4, “The "Hello world"message flow” on page 53. The implementation of the message flow is notfundamentally different. Instead of deploying the message flow to one broker,you need to deploy the message flow to all three brokers. To be able to usethe message flow, we need to make sure that some local queues are defined.

On each broker queue manager, define the local queueHELLO_WORLD.INPUT and make this queue available in the clusterMQSI_CLUSTER. To enable full workload balancing, set the Default Bindfield to Not Fixed. On queue manager MQSI_CONSUMER, create the localqueue HELLO_WORLD.OUTPUT and make it available in the clusterMQSI_CLUSTER. Set the Default Bind field again to Not Fixed as shown inFigure 75:

Figure 75. Queue properties for queue HELLO_WORLD.OUTPUT

If a second message-consuming queue manager is added, one that alsohosted a queue HELLO_WORLD.OUTPUT, the broker would use it too.Basically, the broker uses the MQOPEN option MQOO_BIND_AS_Q_DEF.Thus, this implies that the queue HELLO_WORLD.OUTPUT needs to have

Chapter 4. Advanced setup of MQSeries Integrator 93

the correct value for the Default Bind field to enable workload balancing onthe message-consuming side.

The MQOutput node in the message flow should specify the name of thisqueue, but not the name of the queue manager. See Figure 76.

Figure 76. MQOutput node configuration

4.3.2 Test scenarios in the multi-broker domainThe applications that we used in this setup are again quite simple. On themessage-producing side we have an application that creates 1 KB messagesas quick as it can. On the message-consuming side, we have an applicationthat gets messages off the queue and it reports the message retrieval rate.We will investigate the impact on this parameter by using more than onebroker and by using more than one execution group on a broker and bychanging the persistency of the message.

Note that we force the use of one or two brokers by stopping one or morecluster channels to the broker that we do not want to use. By doing this, theworkload-balancing algorithm on the message-producing queue manager willnot choose these destinations.

Note also that the absolute values of the results are highly dependent on thehardware used. For information about the hardware and software used for

94 Business Integration Solutions with MQSeries Integrator

these tests, please refer to Appendix B, “Hardware and software used for themulti-broker setup” on page 225.

4.3.2.1 Test 1: 1 broker, 5000 persistent messages of 1 KBDuring this test, we saw queuing on the broker’s input queue. The messagearrival rate on the message consuming side was 29 milliseconds permessage or 34 messages per second.

4.3.2.2 Test 2: 1 broker, 5000 nonpersistent messages of 1 KBBy switching to nonpersistent messages, a messages arrived at themessage-consuming side at a rate of one message every 10 milliseconds, or100 messages per second. The impact of persistency is clear.

4.3.2.3 Test 3: 2 brokers, 5000 persistent messages of 1 KBWe started the cluster channel to a second broker queue manager beforelaunching the message generator. During this test, we saw that there wassome significant queuing on the cluster transmission queue at themessage-producing side. However, the message transport was still fasterthan the message handling by both brokers together. On the receiving side,one message arrived every 15 milliseconds, or 66 messages per second. Byadding a second broker, the processing capacity is doubled.

4.3.2.4 Test 4: 2 brokers, 5000 nonpersistent messages of 1 KBUsing nonpersistent messages, the message rate was doubled again. Now,one message arrives every 5 milliseconds, or 200 messages per second.

4.3.2.5 Test 5: 3 brokers, 5000 persistent messages of 1 KBThe increase in message rate is now less important than it was before whenswitching from one broker to two brokers. Basically, the singlemessage-producing queue manager cannot deliver the messages fastenough to the three brokers. The message rate increased to 76 messagesper second, or one message per 13 milliseconds. No or very little queuingwas seen on the broker’s input queue.

4.3.2.6 Test 6: 3 brokers, 5000 nonpersistent messages of 1 KBFor nonpersistent messages, the increase is still significant. The messagerate was 260 messages per second, or one message every 4 milliseconds.

4.3.3 Multi-broker versus multiple execution groupsBy using multiple brokers, the total throughput of the broker domain can beincreased significantly. At the same time, the availability is increased becausethere are now multiple independent paths between the message producer

Chapter 4. Advanced setup of MQSeries Integrator 95

and the message generator. Another way of augmenting the parallelism in thebroker domain is adding an additional execution group. Basically, eachexecution group represents an independent process through which messagesare processed.

Adding an additional execution group is a fairly simple job. In the ControlCenter, go to the Assignments tab and right click on the broker’s name in theleft pane. Select Check Out from the pop-up menu and then select Create ->Execution Group from the pop-up menu. Give the execution group a name.Then drag the message flow from the middle pane to the box representing thenewly defined execution group in the right pane. Repeat these steps for eachbroker. You should end with a view similar to Figure 77.

Figure 77. Brokers with two Execution groups

Save your changes and deploy the Assignment to the brokers. Verify the Logtab to check the successful deployment. You can also check the broker’s input

96 Business Integration Solutions with MQSeries Integrator

queue. The Open Input Count property on the Statistics tab for theHELLO_WORLD.INPUT queue should be increased to two.

4.3.3.1 Test 7: 1 broker, 2 execution groups, 5000 persistentmessages of 1 KB

With the above setup the messages arrived on the consumer side at a rate ofone message every 25 milliseconds, or 40 messages per second. When wecompare this result with the result of Test 1, we see that there is a moderateincrease of message throughput: about 15% more messages were processedper second.

4.3.3.2 Test 8: 1 broker, 2 execution groups, 5000 nonpersistentmessages of 1 KB

Again we see a moderate increase in message throughput. Messages arrivedat a rate of one message per 9 milliseconds.

Taking a closer look at the results and the parameters, it must be noted thatthe processing is mostly CPU bounded: message parsing and messagereformatting involves no I/O. Thus, for single-processor machines andCPU-bounded message flows, it makes more sense to add more brokers thanto add an execution group. The increase for persistent messages is biggerthan it is for nonpersistent messages, because of the logging by the queuemanager. During the I/O operations, the second execution group can use theCPU and push the messages through the message flow. For nonpersistentmessages the difference between one execution group and two is almostinsignificant because here the whole process is completely CPU bounded.

Of course, this does not mean that the concept of a execution group isuseless. The message flow we used here was very simple. Consider amessage flow that involves database operations: message enrichment,message warehousing and so on. For these type of message flows, it makessense to add execution groups. The more the message flow is I/O bounded,the more you can gain by adding the message flow to more than oneexecution group. Also, if the broker runs on a multi-processor box, additionalexecution groups will make better use of the available CPU resources.

On the other hand, having assigned a message flow to more brokers ondifferent machines, will increase message throughput and availability.

For more performance figures involving multiple types of message flows,please refer to the MQSeries Integrator SupportPac MPI4 available at thewebsite http://www-4.ibm.com/software/ts/mqseries/txppacs/mpi4.html.

Chapter 4. Advanced setup of MQSeries Integrator 97

4.4 Summary

In this chapter, we explored some more advanced options to create a brokerdomain. We used a remote and central database for the ConfigurationManager and for the users of the Control Center. We created a multi-brokerdomain that uses MQSeries clusters to increase message rate and brokeravailability. Finally, we compared the use of multiple brokers versus the use ofmultiple execution groups.

98 Business Integration Solutions with MQSeries Integrator

Chapter 5. Example message flow

In this chapter we discuss a richer message flow than the HelloWorldmessage flow in 2.4, “The "Hello world" message flow” on page 53. We lookat a hypothetical order-entry application where the input message comesfrom two different front-end applications in two different formats. Themessage content is used to find the correct location to which the messageshould be routed.

5.1 Overview of the application

The application has two end-user interface programs. The first applicationformulates the orders as an MQSeries message in an XML format. A sampleXML input message looks like this:

<Request><EmpNo>000110</EmpNo><RequestType>NEW </RequestType><OrderNo>99999</OrderNo></Request>

The second, let’s say older, application uses a message with fixed-lengthfields that can be mapped to a C structure definition:

struct Request {char EmpNo[6];char RequestType[6];char OrderNo[6];char WorkDept[3];

}

A sample message using this format is:

000110NEW 999999AAA

The employee serial in the message is used to retrieve the location of theemployee’s department. Based on the location, the correct back-officesystem is selected. The complete message flow is shown in Figure 78. Thenode named XML.PROCESSOR is a composite node for which the detailsare shown in Figure 79 on page 101.

The remainder of this chapter is used to explore all aspects of this messageflow. This includes the use of MQInput and MQOutput nodes, Filter nodes,Compute nodes, using a message flow in another message flow, adding,removing and editing message fields, database access and message

© Copyright IBM Corp. 2000 99

reformatting. Besides the definition of the message flow, we cover the use ofmessage sets and adding a message type to this set by importing a Cstructure definition (a C header file).

Figure 78. Message flow COMPLEX.MSGFLOW

An MQInput node,COMPLEX.XML, accepts the XML data and passes it to anXML.PROCESSOR where database lookups and routing decisions are made.

An MQInput node, COMPLEX.C, accepts incoming byte stream data andpasses it to Compute node CWFtoXML, where it is converted to XML beforebeing passed on to the XML.PROCESSOR. By converting the byte streamdata to XML, the complex database lookups and routing decisions in theXML.PROCESSOR can be used for both the XML and the CWF messages. Itis within CWFtoXML that an MRM/CWF message is needed to allow parsingof the incoming data stream.

Output from the XML.PROCESSOR goes to either the UNITED.KINGDOMqueue, the AMERICA queue, or the DENMARK queue depending upon thelocation of the requesting employee’s department.

There is an MQOutput node and queue associated with the failure terminal ofevery node. This worked well during development and troubleshooting. In a

100 Business Integration Solutions with MQSeries Integrator

production environment it would be wise to give the failure queuesmeaningful names. You might also want to have a single failure queueassigned to several output nodes, instead of having a queue dedicated toeach individual output node.

XML.PROCESSOR is a message flow of itself. Figure 79 contains the details.

Figure 79. Message flow XML.PROCESSOR,

In message flow XML.PROCESSOR, the incoming XML from MQInput nodeCOMPLEX.XML and from Compute node CWFtoXML is parsed, the OrderNofield is altered, a new field called Country is added to the outgoing XML, afield (Workdept) in the incoming CWF message is no longer needed andomitted, a database lookup is done using the employee’s serial number (andsubsequently department number), and routing decisions are made basedupon the employee’s department location.

Using the employee serial number field of the data, a database lookup isdone in the Compute node ComputeCountry to determine the location of theemployee’s department. This requires two database lookups; one using theemployee serial number to obtain the employee’s department number fromthe EMPLOYEE table, and a second lookup in the DEPARTMENT table usingthe department number to determine the location of the department. This isdone with a single ESQL nested (subselect) statement. We will take a look at

Chapter 5. Example message flow 101

the ESQL later. The tables are located in the SAMPLE database that comeswith DB2/ Windows NT. If you have not created this database, you can do itwith the DB2 First Steps application. However, as shipped the LOCATIONfield of the DEPARTMENT table is blank. We set each department location tovalues appropriate for our needs with the following SQL.

The XML message from the ComputeCountry node is first passed to Filternode Filter.UK. If the department location is UNITED KINGDOM the messageis passed out the true terminal to Output terminal Output.UK. Otherwise, itgoes out the false terminal to the Filter node Filter.US. Within Filter nodeFilter.US, if the department location is AMERICA the message is passed tothe Output terminal Output.US. Otherwise it is passed via the false terminal tothe Output terminal Output.Unknown. If there were many countries involvedyou would want to use a more efficient method than this to determine whereto send the messages. In this message flow, only two Filter nodes arerequired.

5.2 Using the Message Repository Manager

Before we explore the message flows, we define first the CWF message.There are three steps needed to create an MRM message from a C structure.

• Create a message set

• Import a C structure to create a new message type within the message set

• Create a message of that new message type

These steps must be done in the order listed. Message types must becontained in a message set, which has to be created first. To create amessage set, select the Message Set tab in the Control Center andright-click the Message Sets folder. Select Create->Message Set.

This SQL was used to set the LOCATION column in the SAMPLE databasevalues useful to our scenario. These commands can be issued fromwithin the DB2 Command Line Processor window.

CONNECT TO SAMPLEUPDATE Database.DEPARTMENT SET LOCATION = 'UNITED KINGDOM'

WHERE DEPARTMENT.ADMRDEPT = 'E01';UPDATE Database.DEPARTMENT SET LOCATION = 'AMERICA'

WHERE DEPARTMENT.ADMRDEPT = 'A00';UPDATE Database.DEPARTMENT SET LOCATION = 'OTHER'

WHERE DEPARTMENT.ADMRDEPT = 'D01';QUIT

102 Business Integration Solutions with MQSeries Integrator

Figure 80. Creating a message set

You will be presented with the following window.

Chapter 5. Example message flow 103

Figure 81. Creating a message set named OrderApplication

Give the message set a name and click Finish. The new message set willappear on your workspace.

We called our message set “OrderApplication”. Then, we used the C importfunction to create the message type, based on a C header file. The C importfunction is accessed by right clicking on the OrderApplication message setand selecting C COBOL Importer... from the pull-down. Initially the new typewill have the same name as the name of the C structure you imported plusthe suffix “_TYPE”.

104 Business Integration Solutions with MQSeries Integrator

Figure 82. Selecting the C COBOL Importer function

You will be presented with the following window to specify the name and fulldirectory of the header file.

Chapter 5. Example message flow 105

Figure 83. Importing a C structure

Provide the full path and file name of the file containing the C structure andselect ‘C’ for the file type. Before you actually import the structure you mightwant to select Report Only to determine if the import would succeed.

The header file contains:

The import function generates a report file that contains an overview of theelements that have been created. The report created when using the importfunction on the file requests.h is as follows:

Importing C header file d:\psehorne\requests.h...

[error 1] line 8: syntax erroractual: [end of file] expecting: &, (, POINTER, ~, struct, union,operator,

class, IDENTIFIER, IDENTIFIER

1 error found during parse.

Importing C structure Request

struct Request {char EmpNo[6];char RequestType[6]; /* valid order types are NEW, CHANGE,

QUERY */char OrderNo[6]; /* if RequestType is not NEW */char WorkDept[3];

}

106 Business Integration Solutions with MQSeries Integrator

EMPNO_LEN value matches Length for this Element. Using this Length.Using defined Element EmpNoREQUESTTYPE_LEN value matches Length for this Element. Using thisLength.Using defined Element RequestTypeORDERNO_LEN value matches Length for this Element. Using thisLength.Using defined Element OrderNoWORKDEPT_LEN value matches Length for this Element. Using thisLength.Using defined Element WorkDeptCreated Type Request_TYPEInserted Element EmpNo into Type Request_TYPEInserted Element RequestType into Type Request_TYPEInserted Element OrderNo into Type Request_TYPEInserted Element WorkDept into Type Request_TYPEC Structure Request successfully imported

Summary:No. of Errors:0No. of Types created:1No. of Elements created:0No. of Lengths created:0

The import function has created all these elements in the database, but theyare not yet available in your workspace. Right-click the Types folder andselect Add to Workspace -> Compound Type...

Chapter 5. Example message flow 107

Figure 84. Selecting Add to Workspace, Compound Type

From the list of types select the one you just imported and click Finish.

108 Business Integration Solutions with MQSeries Integrator

Figure 85. Adding the new Type to your workspace

The next step is to create a message of the type you just imported. To do thisright-click the Messages folder in the OrderApplication message setand thenselect Create->Message.

Chapter 5. Example message flow 109

Figure 86. Creating a message

110 Business Integration Solutions with MQSeries Integrator

Figure 87. Creating a new message of the new type

In the next window you can provide the name you want to give to thismessage. We use the name “Request_MESSAGE”. You also provide anidentifier for the message. We again use “Request_MESSAGE” for theidentifier, although it could be different. The identifier is what you will later usein the MQInput node COMPLEX.C. Also select the type from the Typedrop-down. Then click Finish.

Chapter 5. Example message flow 111

The completed message set will look like this.

Figure 88. Completed message set

5.3 Creating and deploying the message flow

The steps for creating and deploying the message flow are as follows:

• Create the XML.PROCESSOR message flow. This flow needs to becreated before COMPLEX.MSGFLOW since it will be added toCOMPLEX.MSGFLOW

• Create the COMPLEX.MSGFLOW.

• Assign the message set to your broker.

• Assign the message flow to an execution group within your broker.

• Deploy the changes.

112 Business Integration Solutions with MQSeries Integrator

5.4 Details of each node

We will now take a look at each node in some detail in the order that theywould be encountered by an XML message entering the outer message flow(COMPLEX.MSGFLOW) MQInput node COMPLEX.XML. Then we will take alook at how we convert a CWF message to XML via the MQInput nodeCOMPLEX.C and Compute node CWFtoXML so that it can be processed bythe same imbedded message flow (XML.PROCESSOR) as the messagesthat originate as XML.

5.4.1 MQInput node COMPLEX.XMLFigure 89 and Figure 91 are the important configuration windows for thisnode.

Figure 89. MQInput node COMPLEX.XML, Basic tab f

Chapter 5. Example message flow 113

Figure 90. MQInput node COMPLEX.XML, Default tab

The significant configuration items are:

• Queue Name in the Basic tab is set to COMPLEX.XML.

• Message Domain in the Default tab is set to XML.

5.4.2 XML.PROCESSORThis is not just a single node. It is a complete message flow and includesseveral nodes. This is where all of the business logic is encapsulated. TheXML.PROCESSOR is used to process XML messages coming in as XMLthrough the MQInput node COMPLEX.XML and messages that originated asCWF at the MQInput node COMPLEX.C. The only external processing nodeis the CWFtoXML, the node that converts the CWF byte stream data to XML.All other external nodes are either MQInput or MQOutput nodes that do noprocessing.

5.4.2.1 Input and output terminalsInput and Output terminals are a special type of node. TheXML.PROCESSOR message flow is designed to be used in another messageflow, basically as another node. The names of input and output terminals willshow up in the context menu of the node. You can think of input and outputterminals as the exposed functionality of that node/message flow.

The input and output terminals require no special configuration except to saythat during development of XML.PROCESSOR an MQInput node was used toreceive the incoming XML, and MQOutput nodes were used for the outputmessages. Once XML.PROCESSOR was working as desired the MQInputnode was replaced with an input terminal and the MQOutput nodes were

114 Business Integration Solutions with MQSeries Integrator

replaced with Output terminals. This allows XML.PROCESSOR to beimbedded/reused in another message flow. To put a message flow in anothermessage flow, you simply drag it from the list of message flows to theMessage Flow Definition pane.

5.4.2.2 Compute node ComputeCountryFigure 90 is the configuration window for ComputeCountry.

Figure 91. The ComputeCountry ESQL window

The SAMPLE database and DEPARTMENT table were set by clicking theAdd... button on the left side of the window and specifying the name of thedata source and the name of the table. The name of the data source isSAMPLE in our case. You should register the SAMPLE database as an ODBCdata source using the DB2 Client Configuration Assistant.

We are actually querying two tables. It does not matter which table is set withthe Add... button.

Chapter 5. Example message flow 115

The first line of ESQL is generated by selecting Copy entire message.

SET OutputRoot = InputRoot;

The next line shows how to update an existing field. In this case, the OrderNofield is replaced with a constant value, which may not make sense in a reallife situation:

SET OutputRoot.XML.Request.OrderNo = '123456';

This SET statement adds a new field called Country, which does not exist inthe incoming XML message. This field is used later to route the message.

SET OutputRoot.XML.Request.Country = THE(SELECT ITEM D1.LOCATION FROMDatabase.DEPARTMENT AS D1WHERE D1.DEPTNO = THE(SELECT E1.WORKDEPTFROM Database.EMPLOYEE AS E1WHERE E1.EMPNO = InputRoot.XML.Request.EmpNo));

The use of the keyword Database in the SELECT statement is necessary toavoid ambiguity. ESQL can be used to select from a database or from theincoming XML. The keyword THE is also something that makes ESQL lookdifferent from standard SQL. Since a SELECT statement could return a list ofvalues instead of just a single scalar, we could get an error when the syntax ischecked when the message flow is deployed. The error would indicate thatwe are trying to assign a list to a scalar. The keyword THE indicates to thesyntax checker that only one value will be returned and avoids errormessages during deployment.

If the input to the Compute node is:

<Request><EmpNo>000340</EmpNo><RequestType>NEW</RequestType><OrderNo>99999</OrderNo><WorkDept>AAA</WorkDept></Request>

The output will be:

<Request><EmpNo>000340</EmpNo><RequestType>NEW</RequestType><OrderNo>123456</OrderNo><WorkDept>AAA</WorkDept>

116 Business Integration Solutions with MQSeries Integrator

<Country>UNITED KINGDOM </Country></Request>

Notice that the fields in the output message are in the order of appearance inthe input message, because we selected Copy entire message, and the newfield Country is at the end. The same input message in CWF fixed-lengthformat is covered later in this chapter.

5.4.2.3 Filter nodesFilter nodes can test an incoming message for a certain condition.

Figure 92. Filter node Filter.UK

This Filter node checks to see if the Country field in the XML is set to‘UNITED KINGDOM’. If so the message is sent out the true port. Otherwise itis sent out the false port. In this case it is sent to the next Filter node,Filter.US.

Note that you refer to a message using the keyword Body, while you usedInputRoot and OutputRoot in a Compute node. In a Filter node, the messageitself is not transformed. The ESQL statement does not need to differentiatebetween the input message and the output message of the node. However, ina Compute node, the ESQL statements are used to transform the message,hence you need a way to differentiate the input message and the outputmessage.

The Filter node Filter.US is similar to Filter.UK.

Chapter 5. Example message flow 117

Figure 93. Filter node Filter.US

This Filter node checks to see if the Country field in the XML is set toAMERICA. If so, the message is sent out the true port. Otherwise it is sentout the false port.

5.4.3 MQInput node COMPLEX.CFigure 93 and Figure 94 are the important configuration windows for thisnode.

Figure 94. MQInput node COMPLEX.C, Basic tab

118 Business Integration Solutions with MQSeries Integrator

Figure 95. MQInput node COMPLEX.C, Basic tab

The important items here are:

• The Queue Name is COMPLEX.C.

• Message Domain is set to MRM.

• Message set DI3QR8006S001 is the Identifier field of the Message SetOrderApplication.

• Message Type is set to the Identifier field of the MRM message that is tobe used to parse the incoming byte stream. This is Request_MESSAGE,which was also the name of the message.

• Message Format is set to CWF.

The message set identifier is not the name of the message set, but thegenerated string in the Identifier field.

Chapter 5. Example message flow 119

Figure 96. Message set OrderApplication and Message set identifier

5.4.4 Compute node CWFtoXMLThis node takes the CWF byte stream message and converts it to XMLomitting the no longer needed Workdept field.

120 Business Integration Solutions with MQSeries Integrator

Figure 97. Compute node CWFtoXML,

Click the Add button to specify the input message to this Compute node.

In order to convert the CWF to XML it is necessary to include the line:

SET OutputRoot.Properties.MessageFormat = 'XML';

We also have to use OutputRoot.XML in the lines of XML that set the fieldvalues in the output XML message.

The last line of the ESQL is not needed since the Workdept field that thelegacy application is providing is no longer needed now that we are able tolook up the department in real time in the Compute node ComputeCountry. Itis listed here only as an eye catcher, as a reminder that the field is in the inputbut will not appear in the output.

Here is a representative incoming CWF message:

Chapter 5. Example message flow 121

000340NEW 999999AAA

And this is the resulting XML message that will be sent toXML.PROCESSOR.

<Request><EmpNo>000340</EmpNo><RequestType>NEW </RequestType><OrderNo>99999</OrderNo></Request>

5.4.5 MQOutput nodesFigure 98 shows the Basic tab of the AMERICA MQOutput node.

Figure 98. MQOutput node America, Basic tab

We supplied only the queue name. Therefore the connection will be to thedefault queue manager on our local system. You may use both the queuename and queue manager name, the name of an alias queue, or the name ofa remote queue. Nothing was changed in the other tabs.

The other MQOutput nodes are the same. Only the queue name is different.

122 Business Integration Solutions with MQSeries Integrator

Chapter 6. Exploring ESQL

This chapter clarifies some of the ESQL keywords that are used most oftenand that differentiate ESQL from SQL. Given the examples in this chapter youshould be able to get a quick start in the configuration of a Filter or Computenode.

For a complete reference of ESQL please refer to Appendix B of the bookUsing the Control Center, SC34-5602.

6.1 Introduction

ESQL is based upon standard SQL and extends SQL in those areas neededin order to handle messages. Whereas standard SQL can only be usedagainst databases, ESQL can be used to query, update, delete, or alter datawithin messages (either XML or MRM messages) as well as withindatabases. This allows the leveraging of the vast number of technicians whoare already familiar with standard SQL. For those technicians who alreadyknow standard SQL there is a very short learning curve to become familiarwith ESQL.

When using ESQL all data within a generic XML message (generic XMLversus an XML message defined in the MRM) is assumed to be characterdata and casting may be necessary. In some cases casting will be doneimplicitly for you. When messages are defined in the MRM, data types can bedefined for each field.

The XML input message that is used throughout this chapter, as follows:

<OuterElement><Field0>TEXT0</Field0><Field1></Field1><Field2></Field2><Field3></Field3><Field4>TEXT4</Field4><Field5>TEXT5</Field5><Field6>TEXT6</Field6><Field7>TEXT7</Field7><Field8><LASTNAME>SMITH</LASTNAME><FIRSTNME>JOHN</FIRSTNME></Field8><Field9>TEXT9</Field9><Field10>TEXT10</Field10></OuterElement>

© Copyright IBM Corp. 2000 123

6.2 Field manipulations

The following examples show how you can remove a field, add a field, orupdate a field with a new value

6.2.1 Removing a field from the output messageA field that exists in an input message can be omitted from the outputmessage in one of two ways:

1. Explicitly by setting the field to NULL

In a Compute node if you check Copy entire message you can still omit afield by explicitly setting the field to NULL as in the example below.

/* This removes Field0 from the output */SET OutputRoot.XML.OuterElement.Field0 = NULL;

2. Implicitly by ignoring the field

In a Compute node if you check Copy message headers only, you willonly get fields in the output message that you explicitly copy. In this casejust omit the statement that would copy the input field to the outputmessage. Using the example from Chapter 5, “Example message flow” onpage 99, the input message was fixed length data with a format describedby the following C structure:

If you were to select Copy message headers only in a Compute node, thefollowing statements would omit the WorkDept from the output:

This is the C structure we imported. The Type name will default to thestructure nameappended with _TYPE. Thus Request_TYPE will be the type name in this instance.

struct Request {char EmpNo[6];char RequestType[6]; /* NEW, CHANGE, QUERY, CANCEL */char OrderNo[6]; /* if RequestType is not NEW */char WorkDept[3];

}

124 Business Integration Solutions with MQSeries Integrator

The last line is commented out. It is only listed here as an eye catcher toindicate that WorkDept exists in the input message but is not being copied tothe output message.

This method can be used with either MRM described messages or withgeneric XML messages.

6.2.2 Adding new fields in the output messageWhen choosing Copy entire message the order in which existing fieldsappear in the output message reflects the order in which the items appear inthe input message.

New fields can be added after existing fields by inserting additional SETstatements after the statement that copies all input fields to the outputmessage; that is after the statement SET OutputRoot = InputRoot;. If SETstatements are included before the statement SET OutputRoot = InputRoot;they will be overwritten and will not appear in the output.

/* BEFORE: This field did not exist */SET OutputRoot.XML.OuterElement.NewField0 = 'NewText0';SET OutputRoot = InputRoot;/* AFTER: this field does not exist */

The order in which the new fields appear in the output message is determinedby the order of the SET statements in the ESQL. The statements that addnew fields can be interspersed among the statements that set values of theexisting fields. They will still appear at the end of the output message, in theorder in which the SET statements for the new message appeared in theESQL.

SET OutputRoot = InputRoot;/* BEFORE: this field did not exist */

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

SET OutputRoot.*[I] = InputRoot.*[I];SET I=I+1;

END WHILE;

SET OutputRoot.Properties.MessageFormat = 'XML';SET "OutputRoot"."XML"."Request"."EmpNo" = "InputBody"."EmpNo";SET "OutputRoot"."XML"."Request"."RequestType" = "InputBody"."RequestType";SET "OutputRoot"."XML"."Request"."OrderNo" = "InputBody"."OrderNo";--SET "OutputRoot"."XML"."Request"."WorkDept" = "InputBody"."WorkDept";

Chapter 6. Exploring ESQL 125

SET OutputRoot.XML.OuterElement.NewField1 = 'NewText1';/* AFTER: <NewField1>NewText1</NewField1> */

When selecting Copy message headers only the order in which fieldsappear in the output message is determined by the order of the SETstatements in the ESQL.Therefore new fields can be inserted before, after, orbetween existing fields.

For generic XML, the order of fields may not be important. Order may beimportant if the message is supposed to conform to a DTD. Nesting, ofcourse, is important, but the order of fields at the same nesting level may notmatter.

6.3 Database operations

In the following examples we use the SAMPLE database that is part of DB2for Windows NT.

When security is a concern, remember that access to an external databasefrom within a node is done using the same user ID and password as wasspecified when the broker was created for access to the broker’s database.

6.3.1 Qualifying table and column namesSince ESQL can be used against databases or against messages, it isnecessary to qualify database tables with the keyword Database in the FROMportion of the statement to indicate that the statement references columns ina database and not fields in a message. For example:

SET OutputRoot.XML.OuterElement =THE (SELECT D1.LOCATION as Country

FROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

References to column names must be qualified with either the databasename or the alias name used in the AS portion of the FROM clause. Thus theuse of the qualifier D1 in the above example, and the use of the qualifierDEPARTMENT in the example below.

SET OutputRoot.XML.OuterElement.Field1 =THE (SELECT ITEM DEPARTMENT.LOCATION

FROM Database.DEPARTMENTWHERE DEPARTMENT.DEPTNO = 'E21');

126 Business Integration Solutions with MQSeries Integrator

If necessary, a schema may also be used as with normal SQL. For example:

SET OutputRoot.XML.OuterElement =THE (SELECT D1.LOCATION as Country

FROM Database.Schema.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

6.3.2 Usage of keywords THE and ITEMYou can force an ESQL query to return a single (scalar) item rather than a listby using the keyword THE. The keyword THE causes the answer set returnedby the query to be handled as a single item. The first item in the list will beused. In the ESQL queries included here array syntax is not used. Thus anyanswer set that was composed of a list would be expected to fail when beingassigned to a scalar field, that is, it would fail without the use of the keywordTHE. The answer set could be composed of a list of compound items. Use ofthe keyword THE will cause the first compound item in the list to be used. Forexample, if the statement were:

SET OutputRoot.XML.OuterElement.Field7 = THE (SELECT D1.LASTNAME,D1.FIRSTNME from Database.SAMPLE as D1);

The answer set would be a list of compound items,that is, a list of first andlast names. The use of the keyword THE would restrict the answer set to onlythe first compound items. As a result of the above statement Field7 wouldlook like this:

<Field7>TEXT7<LASTNAME>HAAS</LASTNAME><FIRSTNME>CHRISTINE</FIRSTNME></Field7>

Notice that existing text was not overwritten. The tags LASTNAME and FIRSTNMEare added too.

Without the use of ITEM the answer set from a query would be appended tothe specified incoming field data, imbedded in a new field within the existingfield using the name of the database column (or the alias name of the columnspecified in the AS clause) for the name of the new imbedded field. Using ITEMcauses the answer set to be inserted into the specified incoming fieldoverwriting existing data in the field rather than to be appended to anyexisting data.

This example shows the use of keywords ITEM and THE.

/* BEFORE: <Field1></Field1>SET OutputRoot.XML.OuterElement.Field1 =

THE (SELECT ITEM DEPARTMENT.LOCATIONFROM Database.DEPARTMENT

Chapter 6. Exploring ESQL 127

WHERE DEPARTMENT.DEPTNO = 'E21');/* AFTER: <Field1>UNITED KINGDOM </Field1> */

However when using only THE without ITEM, the resulting XML has a new fieldimbedded within the existing field. Note that the new field has the same nameas the column name in the DEPARTMENT table.

/* BEFORE: <Field2></Field2> */SET OutputRoot.XML.OuterElement.Field2 =

THE (SELECT D1.LOCATIONFROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

/* AFTER: <Field2><LOCATION>UNITED KINGDOM </LOCATION></Field2>*/

Using keywords THE and AS, without ITEM, the resulting XML has a new fieldimbedded within the existing field. The name of the field is exactly what hasbeen specified in the AS clause.

/* BEFORE: <Field3></Field3> */SET OutputRoot.XML.OuterElement.Field3 =

THE(SELECT D1.LOCATION AS LocationFROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

/* AFTER: <Field3><Location>UNITED KINGDOM </Location></Field3>*/

When not using the keyword THE, you will get an error during the deploymentof the message flow.

BIP2524W: (5, 1) : Cannot assign to a list to a non-list, nor anot-list to a list.

The following select statement returns one record, because there is only onelocation with department number E21. However the syntax checker does notknow that. Thus, it prevents the deployment of the message flow.

SET OutputRoot.XML.OuterElement.FieldX =(SELECT D1.LOCATIONFROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

6.4 The complete ESQL used in testing the scenarios in this chapter

The following ESQL stream was used to explore and test the scenariosdescribed above.

/* ===== Section separator =====*/

128 Business Integration Solutions with MQSeries Integrator

/* In the SET statement that follows NewField0, which does not existin the input message, will get overwritten by the SET statement 'SETOutputRoot = InputRoot;' which follows it. NewField0 will not appearin the output.*//* BEFORE: This field did not exist */SET OutputRoot.XML.OuterElement.NewField0 = 'NewText0';/* AFTER: this field does not exist */

/* ===== Section separator ===== *//* This copies all input fields to the output. This line was addedwhen we clicked on "Copy entire message". It will overwrite theabove SET statement. */SET OutputRoot = InputRoot;/* The fields of the input message will appear in the output messagein the same order as in the input message regardless of the order ofthe statements below. */

/* ===== Section separator ===== *//* This removes Field0 from the output *//* BEFORE: <Field0>TEXT0</Field0> */SET OutputRoot.XML.OuterElement.Field0 = NULL;/* AFTER: Field0 is not included in the output */

/* ===== Section separator ===== *//* This adds a new field AT THE END of the message even though itappears way up here in the list of SET STATEMENTS. *//* BEFORE: this field did not exist */SET OutputRoot.XML.OuterElement.NewField1 = 'NewText1';/* AFTER: <NewField1>NewText1</NewField1> */

/* ===== Section separator =====*//* THE NEXT FEW QUERIES RETURN ONLY ONE ROW. *//* However, the syntax checker does not know that at runtime thequeries only return one row. */

/* ===== Section separator =====*//* Using both 'THE' and 'ITEM' works as expected. It replaces textin the incoming field. *//* Note: 'AS' cannot be combined with ITEM. *//* BEFORE: <Field1></Field1> */SET OutputRoot.XML.OuterElement.Field1 =

THE (SELECT ITEM DEPARTMENT.LOCATIONFROM Database.DEPARTMENTWHERE DEPARTMENT.DEPTNO = 'E21');

Chapter 6. Exploring ESQL 129

/* AFTER: <Field1>UNITED KINGDOM </Field1> */

/* ===== Section separator ===== *//* Using only 'THE' without ‘ITEM’ results in a new field, LOCATION,being imbedded within existing incoming Field2 */

/* BEFORE: <Field2></Field2> */SET OutputRoot.XML.OuterElement.Field2 =

THE (SELECT D1.LOCATIONFROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

/* AFTER: <Field2><LOCATION>UNITED KINGDOM </LOCATION></Field2> */

/* ===== Section separator ===== *//* Using only 'ITEM' without 'THE' *//* This whole section is commented out because you can't assign alist to a scalar and the answer set from the query could be a list.The error returned during deployment is “BIP2524W: (5, 1): Cannotassign to a list to a non-list, nor a not-list to a list.” Thiserror can be avoided with the use of keyword ‘THE’, assuming thatyou know that at runtime only one item will be returned from thelist, or if you are happy to use the first item from the answer setif a list of items is returned.

SET OutputRoot.XML.OuterElement.FieldX =(SELECT ITEM D1.LOCATIONFROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

*/

/* ===== Section separator ===== *//* Using only 'THE' with 'AS' without 'ITEM' results in a new field,Location, being imbedded within incoming existing Field3 *//* BEFORE: <Field3></Field3> */SET OutputRoot.XML.OuterElement.Field3 =

THE(SELECT D1.LOCATION AS LocationFROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

/* AFTER: <Field3><Location>UNITED KINGDOM </Location></Field3> */

/* ===== Section separator ===== *//* Using neither 'THE' nor 'ITEM' *//* Commented out because it returns an error, during deploymentBIP2524W: (5, 1) : Cannot assign to a list to a non-list, nor anot-list to a list.

130 Business Integration Solutions with MQSeries Integrator

SET OutputRoot.XML.OuterElement.FieldX =(SELECT D1.LOCATIONFROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

*/

/* ===== Section separator ===== *//* THE FOLLOWING QUERIES RETURN MORE THAN ONE ROW *//* The results are the same as above queries which return only onerow, except that the actual data returned by the query is different.*/

/* ===== Section separator ===== *//* Using both 'THE' and 'ITEM' works as desired by replacing text inincoming existing Field4 */

/* BEFORE: <Field4>TEXT4</Field4> */SET OutputRoot.XML.OuterElement.Field4 =

THE (SELECT ITEM D1.LOCATIONFROM Database.DEPARTMENT AS D1);

/* AFTER: <Field4>AMERICA </Field4> */

/* ===== Section separator ===== *//* Using only 'THE' without 'ITEM' imbeds a new field, LOCATION (thename of the database column), within existing Field5 while leavingthe existing text of Field5 untouched */

/* BEFORE: <Field5>TEXT5</Field5> */SET OutputRoot.XML.OuterElement.Field5 =

THE (SELECT D1.LOCATIONFROM Database.DEPARTMENT AS D1);

/*AFTER: <Field5>TEXT5<LOCATION>AMERICA </LOCATION></Field5>*/

/* ===== Section separator ===== *//* Using only 'THE' without 'ITEM' same as above except added "ASLocation" to specify that the new field name should be called"Location" */

/* BEFORE: <Field6>TEXT6</Field6> */SET OutputRoot.XML.OuterElement.Field6 =

THE (SELECT D1.LOCATION AS LocationFROM Database.DEPARTMENT AS D1);

Chapter 6. Exploring ESQL 131

/* AFTER: <Field6>TEXT6<Location>AMERICA</Location></Field6> */

/* ===== Section separator ===== *//* 'THE' without 'ITEM' with a list */

/* BEFORE: <Field7>TEXT7</Field7> */SET OutputRoot.XML.OuterElement.Field7 =

THE (SELECT D1.LASTNAME, D1.FIRSTNMEfrom Database.EMPLOYEE as D1);

/* AFTER:<Field7>TEXT7<LASTNAME>HAAS</LASTNAME><FIRSTNME>CHRISTINE</FIRSTNME></Field7> */

/* ===== Section separator ===== *//* 'THE' without 'ITEM' with a list *//* This is only different from the above because input Field8contains different data. *//* BEFORE:<Field8><LASTNAME>SMITH</LASTNAME><FIRSTNME>JOHN</FIRSTNME></Field8> */SET OutputRoot.XML.OuterElement.Field8 =

THE (SELECT D1.LASTNAME, D1.FIRSTNMEfrom Database.EMPLOYEE as D1);

/* AFTER:<Field8><LASTNAME>SMITH</LASTNAME><FIRSTNME>JOHN</FIRSTNME><LASTNAME>HAAS</LASTNAME><FIRSTNME>CHRISTINE</FIRSTNME></Field8> */

/* ===== Section separator =====*//* The following two SET statements accomplish the goal of theattempts above to replace Field7 and Field8 data with new datainstead of appending to them. *//* Here we first remove Field9 by setting it to NULL. Then we add itback with new data. This will have the side affect of moving Field9into the area of the output message occupied by other new fields. */SET OutputRoot.XML.OuterElement.Field9 = NULL;

/* Next Field9 is added back into the output with new data. *//* BEFORE: <Field9>TEXT9</Field9> */SET OutputRoot.XML.OuterElement.Field9 =

THE (SELECT D1.LASTNAME, D1.FIRSTNMEfrom Database.EMPLOYEE as D1);

/* AFTER:<Field9><LASTNAME>HAAS</LASTNAME><FIRSTNME>CHRISTINE</FIRSTNME></Field9> */

132 Business Integration Solutions with MQSeries Integrator

/* ===== Section separator ===== *//* Using neither 'THE' nor 'ITEM' returns an error during deployment“BIP2524W: (5, 1): Cannot assign to a list to a non-list, nor anot-list to a list. “. So this whole section is commented out.

SET OutputRoot.XML.OuterElement.FieldX =(SELECT D1.LOCATIONFROM Database.DEPARTMENT AS D1);

*/

/* ===== Section separator ===== *//* Using only 'ITEM' without 'THE' *//* This whole section is commented out because attempt to assign alist to a scalar results in an error during deployment. “BIP2524W:(5, 1) : Cannot assign to a list to a non-list, nor a not-list to alist. “SET OutputRoot.XML.OuterElement.FieldX =

(SELECT ITEM D1.LOCATIONFROM Database.DEPARTMENT AS D1);

*/

/* ===== Section separator ===== *//* Using neither 'THE' nor 'ITEM' also returns an error duringdeployment “BIP2524W: (5, 1): Cannot assign to a list to a non-list,nor a not-list to a list. “. So this section is also commented out.SET OutputRoot.XML.OuterElement.FieldX =

(SELECT D1.LOCATIONFROM Database.DEPARTMENT AS D1);

*/

/* ===== Section separator ===== *//* THE FOLLOWING QUERIES RETURN ONLY ONE ROW. *//* Using only 'THE' and no inner field name with a query that onlyreturns one item adds a new field with the same name as the databasecolumn, LOCATION, at the end of OuterElement */

SET OutputRoot.XML.OuterElement =THE (SELECT D1.LOCATION

FROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

/* AFTER: <LOCATION>UNITED KINGDOM </LOCATION> */

/* ===== Section separator ===== */

Chapter 6. Exploring ESQL 133

/* same as the above but with the addition of "as Country" as analias for the column name. This adds a new field called Country atthe end of, but within, OuterElement */

SET OutputRoot.XML.OuterElement =THE (SELECT D1.LOCATION as Country

FROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

/* AFTER: <Country>UNITED KINGDOM </Country> */

/* ===== Section separator =====*//* Same as the above except NO existing element AT ALL, not evenOuterElement. This failed at runtime with “ParserExceptionBIP5005E: No valid body of the document could be found. NoxmlElement, xmlElementFav or xmlEmptyElement was found as a child ofthe root() or there was more than one of them as children in theroot();. Check that the XML message being passed in is a well formedXML message that adheres to the XML specification and that only oneof the above exists as a child of the root();.”

SET OutputRoot.XML =THE (SELECT D1.LOCATION as Country

FROM Database.DEPARTMENT AS D1WHERE D1.DEPTNO = 'E21');

*/

/* ===== Section separator ===== *//* New fields being added will appear in the output in the order ofthe associated SET statements */

SET OutputRoot.XML.OuterElement.NewField2 = 'NewText2';/* AFTER: <NewField2>NewText2</NewField2> */

6.5 XML output message

Notice that there are blank lines where Field0 and Field9 were removed, andthe Field9 was added back in after the original message in the order ofappearance of all of the lines that added new fields.

<OuterElement>

<Field1>UNITED KINGDOM </Field1><Field2><LOCATION>UNITED KINGDOM </LOCATION></Field2><Field3><Location>UNITED KINGDOM </Location></Field3><Field4>AMERICA </Field4>

134 Business Integration Solutions with MQSeries Integrator

<Field5>TEXT5<LOCATION>AMERICA </LOCATION></Field5><Field6>TEXT6<Location>AMERICA </Location></Field6><Field7>TEXT7<LASTNAME>HAAS</LASTNAME><FIRSTNME>CHRISTINE</FIRSTNME></Field7><Field8><LASTNAME>SMITH</LASTNAME><FIRSTNME>JOHN</FIRSTNME><LASTNAME>HAAS</LASTNAME><FIRSTNME>CHRISTINE</FIRSTNME></Field8>

<Field10>TEXT10</Field10><NewField1>NewText1</NewField1><Field9><LASTNAME>HAAS</LASTNAME><FIRSTNME>CHRISTINE</FIRSTNME></Field9><LOCATION>UNITED KINGDOM </LOCATION><Country>UNITED KINGDOM </Country><NewField2>NewText2</NewField2></OuterElement>

Chapter 6. Exploring ESQL 135

136 Business Integration Solutions with MQSeries Integrator

Chapter 7. Developing your own plug-in

This chapter explains how to extend the functionality of MQSeries Integrator.We explain the concepts and the requirements for the implementation of aso-called loadable implementation library or lil. Next, we discuss in detail asample plug-in and go through the steps to make the plug-in available for usein the Control Center and in the broker.

7.1 Terminology

In discussions about the framework that MQSeries Integrator provides forextending its functionality, a number of terms are used: plug-in, user-writtennode, a user-written parser, a lil.

A plug-in is a generic name for any type of function that can be added to yourMQSeries Integrator environment.

A user-written node or node is a first type of plug-in. It is the type of plug-inthat you can add to the palette of the Control Center. The function that auser-written node can provide is very broad. It can route the message to oneof its output terminals based on some specialized logic that is not easy toexpress in a Compute node. It can edit the message by accessing externalresources and so on.

A parser is a second type of plug-in. You can decide to write your own parserfor specialized messages that you cannot or do not want to express in theMessage Repository Manager (MRM).

Finally, a loadable implementation library or a lil is the implementation modulefor one or more nodes or one or more parsers. A lil is implemented as adynamic link library (DLL) on the Windows NT platform. It does not have thefile extension .dll but .lil.

The remainder of this chapter will focus on the implementation of auser-written node, which can significantly enhance the functionality ofMQSeries Integrator.

7.2 Overview of the requirements for your plug-in

Given that a plug-in is used at the heart of a broker, it is clear that there aresome specific requirements for the implementation of your plug-in: APIrequirements, memory management, exception management and threadingissues.

© Copyright IBM Corp. 2000 137

7.2.1 API requirementsThere are a number of specific functions that a module must implement. Werefer to these functions as implementation functions. Your lil can also use thefunctionality of the broker by calling utility functions. And finally you have theinitialization function. This last function, with the namebipGetMessageflowNodeFactory, is called by the broker after the lil has beenloaded and initialized by the operating system. The broker calls this functionto understand what your lil is able to do and how the broker should call the lil.

To express what your lil can do, or better what nodes your lil supports, thebipGetMessageflowNodeFactory function has to call the utility functioncniCreateNodeFactory. This function passes back a factory name (or groupname) for all the nodes that your lil supports. Next, the lil should call the utilityfunction cniDefineNodeClass to pass the name of each node and a virtualfunction table of the addresses of the implementation functions.

To make the above more concrete, refer to 7.3.3, “Implementation details ofthe Switch node” on page 146 for a code snippet.

Because you are passing function pointers, you are free to choose the nameof your implementation functions. Their signature is fixed, of course. The listbelow specifies what functions you have to implement:

• cniCreateNodeContext

• cniGetAttributeName

• cniGetAttribute

• cniSetAttribute

• cniEvaluate

When the broker has received the table of function pointers, it will call thefunction cniCreateNodeContext for each instantiation of the plug-in. If youhave three message flows that are using your plug-in, yourcniCreateNodeContext function is called for each of them. This functionshould allocate memory for that instantiation of the plug-in to hold the valuesfor the configured attributes. Next it should call the appropriate utilityfunctions to tell the broker about the input terminals and the output terminalsit supports. Note that this must be done during cniCreateNodeContext. Nextthe broker calls the cniSetAttribute function to pass the values for theconfigured attributes for this instantiation of the plug-in.

At this point the instantiation of the plug-in is finished. When the brokerretrieves a message from the queue and that message arrives at the inputterminal of your plug-in, the broker will call the implementation function

138 Business Integration Solutions with MQSeries Integrator

cniEvaluate. This function should decide what to do with the message:propagate the message to a terminal and eventually transform the message.

7.2.2 Implementation requirements and restrictionsMessage flows can be used in multiple execution groups and in multiplethreads at the same time. Therefore, the implementation of a node needs tobe thread-safe and avoid the use of any global data.

To avoid creating orphaned memory, the node should make sure that allmemory acquired by the node is released at some point.

All data passed between the broker and the plug-in is coded in a widecharacter set, even for attributes in an integer format. The implementationfunctions cniSetAttribute and cniGetAttribute should make sure that thenecessary conversions are done with data received from the broker or passedback to the broker.

The plug-in should also limit the use of any operating system-specificfunctions. The use of external configuration parameters, such as environmentvariables or ini files, should be avoided because the broker cannot assist indistributing these resources. MQSeries Integrator is designed in such a waythat brokers can be administered from remote locations. If a plug-in requiresexternal data, you should make sure that this data is available before thedeployment of a message flow using the plug-in.

And finally, here are some considerations about exception management anderrors. When a plug-in calls utility functions that execute in the broker, thereturn code parameter will contain an indication of any error conditions. Theplug-in should test the value and perform any recovery operations if needed.The utility function cciGetLastExceptionData can then be used to obtain moreinformation about the error. Once the plug-in has done its logging andrecovery, the exception should be passed back to the broker again by callingthe utility function cciRethrowLastException. The plug-in itself can also raiseexceptions using the utility function cciThrowException. It is critical for theintegrity of the broker that a plug-in respects and uses these exceptionmanagement functions.

7.3 Developing a Switch node

Recall the message flow that was discussed in Chapter 5, “Example messageflow” on page 99, we used a number of Filter nodes to determine the rightqueue for the message. In this scenario, we had only three countries to filteron. However, you can easily imagine situations where many cases are

Chapter 7. Developing your own plug-in 139

possible. We tried to find an easier way to express this routing. Actually, whatwe needed was the graphical building block to express the well-known Clanguage construct:

switch <expression>{case: <value1>;

case: <value2>;

...case: <valueN>;

}

7.3.1 Design of the Switch nodeThe ideal solution would be that you have a plug-in with configurable outputterminals. In the configuration pages of the node, you should then specify thepossible values and the plug-in should create the output terminals on the fly.Unfortunately, this is not possible. The Control Center has only some staticinformation about the plug-in. The lil itself is not used or called by the ControlCenter. To understand how the Control Center knows your plug-in and itscharacteristics, refer to 7.3.2, “Making the plug-in available in the ControlCenter” on page 141.

Given the above limitation, it is not obvious to develop a real generic Switchnode that is equivalent to the C switch statement. Therefore the currentimplementation is maybe too simple but hopefully it will help the readerunderstand how a plug-in node works.

When the plug-in’s cniEvaluate function is called, the plug-in will traverse themessage tree to find the first occurrence of the element Country. The plug-inwill use a depth-first algorithm. When no occurrence of the element Countryis found, the message is propagated to the failure terminal. If an occurrenceis found, the value is compared with the three countries that were usedbefore: America, United Kingdom and Denmark. If the element Country has adifferent value, the message is routed again to the failure terminal.

To assist in debugging and in problem reporting, the node supports twoconfigurable attributes:

• nodeTraceSetting with possible values 0 or 1 to enable or disable internaltracing of the node

• nodeTraceOutfile to specify the name and the directory for the trace file

140 Business Integration Solutions with MQSeries Integrator

A possible extension could be to allow configuration of the name of theelement. However, given the fact that the output terminals are fixed, thisextension does not add much functionality.

7.3.2 Making the plug-in available in the Control CenterBefore you can start using a user-written node in the Control Center, youneed to prepare a number of files that describe the node and a number of GIFfiles to be used in the Control Center.

The first configuration file has the name Switch, without an extension. Thisname is derived from the name used in utility function cniDefineNodeClass.Drop the suffix Node to know the name of the first configuration file. This fileis also known as the XML interface definition.

cniDefineNodeClass(0, factoryObject, L"SwitchNode", &vftable);

This file Switch is in an XML format and it specifies the configurableattributes, the input and the output terminals and the GIF files:

<Attribute xmi.label=”nodeTraceOutFile” type=”String” value=””xmi.uuid=”” valueMandatory=false encoded=”fales”/><Attribute xmi.label=”nodeTraceSetting” type=”Integer” value=”0”xmi.uuid=”” valueMandatory=false encoded=”fales”/>

The above specification determines what attributes the plug-in knows, theirdatatype, a default value and if it is mandatory to specify a value.

Input and output terminals are defined as follows:

<OutTerminal longDescription=”” icon=”images/OutTerminal.gif”versionCreator=”” shortDescription=”” creationTimeStamp=””creator=”” y=”0” x=”0” versionTimeStamp=””xmi.uuid=”020c000c-0800-0000-0100-090507050000”xmi.label=”America”>.

A similar XML stream is needed for each input terminal. If your lil implementsmultiple nodes, you need such a file for each node. This file needs to becopied to the directory:

Tool\repository\private\<hostname>\<configmgr queuemanager>\MessageProcessingNodeType

The second file you need to prepare is a properties file. The name of the fileis again the name of the node, without the suffix Node, and has the fileextension WDP. In our case here, the file is called Switch.wdp. The file shouldreside in the same directory as the XML interface definition file. The most

Chapter 7. Developing your own plug-in 141

important parameters in this file are the label and the GIF file that are used torepresent the node on the palette.

The third file is optional. Its intention is to provide some contextual help in theControl Center. The file is referred to as the Node properties file. Its name isthe name of the node without the suffix Node and has the file extensionproperties. In our case, the file is called Switch.properties. The file should becopied into the directory Tool\com\ibm\ivm\mqitools\extension.

The contents of our properties file is as follows:

shortDescription = Sample fixed switch based on content of aninput messagelongDescription = The SampleSwitch node is an example of a pluginmessage processing nodenodeTraceSetting = Trace setting for the nodenodeTraceOutFile = Trace output file name

In the following figures you see where this information is displayed:

142 Business Integration Solutions with MQSeries Integrator

Figure 99. Visualization of the short description

By selecting the Switch node in the palette, the short description is shown inthe left corner near the bottom.

By right-clicking the Switch node in the palette and selecting Properties, yousee the following window:

Chapter 7. Developing your own plug-in 143

Figure 100. Properties window of the Switch node

Here you see that the default value for the trace setting is filled in. Selectingthe Description tab, you see the short and long description that you havespecified in the properties file.

Figure 101. Description tab for the Switch node

Finally you need five GIF files. The first GIF file was used to represent theSwitch node on the palette. It had the name SwitchNode.gif, as specified inthe XML interface definition file Switch. The names of the four others are

144 Business Integration Solutions with MQSeries Integrator

derived from that one and are the four icons to be used in the Message FlowDefinition pane. Right-click in the Message Flow Definition pane and selectthe Zoom option. You see there four scaling options: 100%, 75%, 50% and25%. For each scaling option you need to have a GIF file. The names of theGIF files are then:

• SwitchNode30.gif

• SwitchNode42.gif

• SwitchNode58.gif

• SwitchNode84.gif

These numbers are basically the height (and width) of the images expressedin pixels. The five files need to be copied in the Tool\images directory.

When you have copied all the files to the right directory, you are ready to loadthe node in the Control Center. It might be a good idea to create a separateMessage Flow Category for your user-written plug-ins. Right-click theMessage Flows folder in the Message Flow Types pane and select Create ->Message Flow Category. Specify a name you like (we used User-writtenPlug-ins) and click the Finish button to close the window. Then, select thenewly created message flow category. Right-click it and select Add ->Message Flow. You will be presented with a list that includes the Switchplug-in. Select it and click the Finish button. Your Control Center will nowshow the plug-in and you are ready to use it. The Control Center will look likeFigure 99 on page 143.

The last thing to do is to make the broker aware of your plug-in. Copy the DLLinto the bin directory of MQSeries Integrator, rename the DLL to have theextension lil and restart the broker. Note that the broker loads all lils in the bindirectory during its startup phase, even if the broker has no message flowsthat are using the node that is implemented in the lil.

The following table summarizes the configuration files and the location whereMQSeries integrator expects them.

Chapter 7. Developing your own plug-in 145

7.3.3 Implementation details of the Switch nodeNote in this section that the code snippets are stripped down to include onlythe relevant things. Comments and statements for tracing are removed whereappropriate.

As explained before, the processing in the lil starts with the functionbipGetMessageflowNodeFactory. The function calls the broker’s utilityfunction to create the node factory. The internal function defineSwitchNodefills up the factoryObject variable with the addresses of the implementationfunctions.

CciFactory LilFactoryExportPrefix * LilFactoryExportSuffixbipGetMessageflowNodeFactory(){CciFactory* factoryObject;int rc = 0;CciChar factoryName[] = L"SwitchNodeFactory";CCI_EXCEPTION_ST exception_st;

/* Create the Node Factory for this plug-in */factoryObject = cniCreateNodeFactory(0, factoryName);if (factoryObject == CCI_NULL_ADDR) {if (rc == CCI_EXCEPTION) {/* Get details of the exception */cciGetLastExceptionData(&rc, &exception_st);

/* Any local error handling may go here */

/* Rethrow the exception */cciRethrowLastException(&rc);

}

file location

lil MQSI Root\bin

GIF MQSI Root\tool\images

properties MQSIRoot\tool\com\ibm\ivm\mqitools\extension

wdpno extension

MQSIRoot\tool\repository\private\<hostname>\<ConfigMgrQMName>\MessageProcessingNodeType

146 Business Integration Solutions with MQSeries Integrator

/* Any further local error handling can go here */}else {/* Define the nodes supported by this factory */defineSwitchNode(factoryObject);

}

/* Return address of this factory object to the broker */return(factoryObject);

}

In the internal function defineSwitchNode, we call the utility functioncniDefineNodeClass to pass the name of the node. It is this name that is usedto build the file names (refer to 7.3.2, “Making the plug-in available in theControl Center” on page 141) and to match whatever has been used in theconfiguration of the message flow.

void defineSwitchNode(void* factoryObject){static CNI_VFT vftable;

/* Setup function table with pointers to node implementationfunctions */memset(&vftable, 0, sizeof(vftable));vftable.iFpCreateNodeContext = _createNodeContext;vftable.iFpDeleteNodeContext = _deleteNodeContext;vftable.iFpGetAttributeName = _getAttributeName;vftable.iFpSetAttribute = _setAttribute;vftable.iFpGetAttribute = _getAttribute;vftable.iFpEvaluate = _evaluate;

cniDefineNodeClass(0, factoryObject, L"SwitchNode", &vftable);

return;}

Once the broker knows the addresses of the implementation function, he callsthe cniCreateNodeContext function to give the lil the opportunity to initializeinternal data structures. The major data structure is theNODE_CONTEXT_ST structure for which the definition is shown as follows:

Chapter 7. Developing your own plug-in 147

typedef struct context {CciNode* nodeObject; /* Handle for node object */ATTRIBUTE_TBL_ENTRY* attrListHead; /* Head of linked list of

attributes */ATTRIBUTE_TBL_ENTRY* attrListPrevious; /* Previous entry in attribute

list */TERMINAL_LIST_ENTRY* inputTerminalListHead; /* Head of linked list of

input terminal handles */TERMINAL_LIST_ENTRY* inputTerminalListPrevious; /* Previous entry in input

terminal list */TERMINAL_LIST_ENTRY* outputTerminalListHead; /* Head of linked list of

output terminal handles */TERMINAL_LIST_ENTRY* outputTerminalListPrevious; /* Previous entry in output

terminal list */int trace; /* Flag: Trace active? */FILE* tracefile; /* Trace file stream */CciChar nodeName[MAX_NODE_NAME_LEN]; /* Node name */

} NODE_CONTEXT_ST;

The context is used to store the list of input and output terminals and the listof attributes with their data type and value. The address of this structure ispassed to the broker and the broker guarantees that it will call theimplementation functions with the correct pointer to this context. If your nodeis used in two deployed message flows, you will have to create two contextstructures. When the broker needs to call the cniEvaluate function for the firstmessage flow, it will pass it the address of the context structure created forthe first message flow.

In the cniCreateNodeContext function you also see the use of the compilerdirective to enable tracing before we know about the configured file name. Itshould be stressed that this is only useful when debugging the lil.

CciContext* _createNodeContext(CciFactory* factoryObject,CciChar* nodeName,CciNode* nodeObject

){NODE_CONTEXT_ST* p;

/* Allocate a pointer to the local context */p = malloc(sizeof(NODE_CONTEXT_ST));

if (p) {

/* Clear the context area */

148 Business Integration Solutions with MQSeries Integrator

memset(p, 0, sizeof(NODE_CONTEXT_ST));

/* Save our node object pointer in our context */p->nodeObject = nodeObject;

/* Save our node name */wcsncpy((wchar_t*)&p->nodeName, nodeName, MAX_NODE_NAME_LEN);

/* Initialize default trace setting */#ifdef _DEBUG

p->trace = 1;p->tracefile = fopen("C:\\SwitchNode.trc", "a+");

#elsep->trace = 0;p->tracefile = NULL;

#endif

/* Create attributes and set default values */insAttrTblEntry(p, L"nodeTraceOutfile", CNI_TYPE_STRING);insAttrTblEntry(p, L"nodeTraceSetting", CNI_TYPE_INTEGER);

/* for the debug version of this modules, turn on early tracing*/#ifdef _DEBUG

_setAttribute(p, L"nodeTraceOutfile", L"C:\\SwitchNode.trc");#else

_setAttribute(p, L"nodeTraceOutFile", L"");#endif

#ifdef _DEBUG_setAttribute(p, L"nodeTraceSetting", L"1");

#else_setAttribute(p, L"nodeTraceSetting", L"0");

#endif

/* Create terminals */insInputTerminalListEntry(p, L"in");insOutputTerminalListEntry(p, L"America");insOutputTerminalListEntry(p, L"Denmark");insOutputTerminalListEntry(p, L"United Kingdom");insOutputTerminalListEntry(p, L"failure");

}else {/* Error: Unable to allocate memory */

}

Chapter 7. Developing your own plug-in 149

displayEnvironment(p);

/* Return the pointer to the local context */return((CciContext*)p);

}

The cniSetAttribute and cniGetAttribute functions are not shown here. Thesefunctions do nothing more than search the correct attribute in the linked list.However, one thing is important to know. All attributes are passed to the lil aswide-character strings, even for attributes of type integer. It’s up to the lil to dothe necessary checking and conversion. In the cniSetAttribute function, this isaccomplished with the following instruction for integer type attributes:

*((int *)p->valptr) = _wtoi(attrValue);

where p is a pointer to an entry of the attribute list.

The cniEvaluate function is more interesting to have a closer look at it. Itshows “how to find your way” in a message using the message navigationutility functions. To understand the navigation, please look at Figure 102. Amessage is built up as a tree with a root element called Root. To get a pointerto this root element, you use the utility function cniRootElement with yourmessage as an argument. The root element has four children: Properties, thestandard MQSeries Message Descriptor MQMD, the Rules and Formatterheader MQRFH2 and finally as a last child, the root of the message dataitself. The root of the message data is called after the message domain,which was in our test messages XML. Thus, giving the root element of yourmessage, you get to the message data using the utility function cniLastChild.

Figure 102. First level of the message tree representation

Starting from the XML node in the message tree, the tree can be seen inFigure 103 on page 153. The XML node has one child, which is Message. To

Root

Properties MQMD MQRFH2 XML

150 Business Integration Solutions with MQSeries Integrator

get a pointer to this node, you use the utility function cniFirstChild. Theresult is passed to the internal function findElementName to find theelement with the name Country.

void _evaluate(CciContext* context,CciMessage* destinationList,CciMessage* exceptionList,CciMessage* message

){static wchar_t* functionName=L"_evaluate()";CCI_EXCEPTION_ST exception_st;NODE_CONTEXT_ST* nc = context;CciElement* bodyChild;CciElement* firstChild;CciElement* rootElement;CciElement* element;CciTerminal* terminalObject;int bytes;int rc;int retvalue = 1;CciChar elementValue[256];CciChar elementName[256];

/* Get the root element and it's name */rootElement = cniRootElement(&rc, message);

/* Get the last child of root (ie the body) and it's name */bodyChild = cniLastChild(&rc, rootElement);cniElementName(&rc, bodyChild, (CciChar*)&elementName,

sizeof(elementName));

/* Traverse to <Country> */

/* Navigate to the root of the XML message */firstChild = cniFirstChild(&rc, bodyChild);

element = findElementName(firstChild, L"Country", nc);if (element == 0){/* message has no element with the right name */terminalObject = getOutputTerminalHandle(context, L"failure");

}

else

Chapter 7. Developing your own plug-in 151

{bytes = cniElementCharacterValue(&rc, element,

(CciChar*)&elementValue, sizeof(elementValue));

/* Decide which output terminal should receive the message,based on the value */

if (wcscmp(elementValue, L"America") == 0)terminalObject = getOutputTerminalHandle(context, L"America");else if (wcscmp(elementValue, L"Denmark") == 0)terminalObject = getOutputTerminalHandle(context, L"Denmark");

else if (wcscmp(elementValue, L"United Kingdom") == 0)terminalObject = getOutputTerminalHandle(context, L"United

Kingdom");else {terminalObject = getOutputTerminalHandle(context, L"failure");

}}

/* If the terminal exists and is attached, propagate to it */if (terminalObject) {if (cniIsTerminalAttached(&rc, terminalObject)) {if (rc == CCI_SUCCESS) {retvalue = cniPropagate(&rc, terminalObject,

destinationList, exceptionList, message);if (rc != CCI_SUCCESS) {if (rc == CCI_EXCEPTION) {/* Get details of the exception */cciGetLastExceptionData(&rc, &exception_st);

/* Any local error handling may go here */

/* If the exception is "caught" it must be re-thrown */cciRethrowLastException(0);

}/* Some other error...log it */

}else {/* Message was propagated successfully */

}}else {if (rc == CCI_EXCEPTION) {cciRethrowLastException(0);

}else {

152 Business Integration Solutions with MQSeries Integrator

/* Some other error...log it */cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "",

L"MQSeriesIntegrator2", 0, "Error occurred", 0);}

}}

}else {/* Terminal did not exist...severe internal error */cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "",

L"MQSeriesIntegrator2", 0, "Terminal not connected", 0);}return;

}

Figure 103. Message tree representation for the message data

If findElementName was able to get a pointer to an element called Country,we retrieve the value of that element by calling the utility functioncniElementCharacterValue. The value is compared with the expected valuesand the handle of the corresponding output terminal is looked up in the linkedlist addressed via the context. If the terminal is attached, we call the utilityfunction cniPropagate to route the message through that terminal.

The last function we want to investigate in detail is the findElementNamefunction that traverses the message tree to find the first element in the treewith a given name. The traversal of a tree is typically implemented using arecursive function. Other non-recursive algorithms exist, but for simple treeswith not too much nesting, recursion does well. When using recursion, you

M e ss a g e

N a m e

X M L

N a m e

C ity

N a m e

C o u n try

N a m e

"C a ry"

V a lu e

"A m e ric a "

V a lu e

Chapter 7. Developing your own plug-in 153

have two options. You can choose the depth-first option where the traversal isgoing from parent to child. When all child nodes are explored, the traversalsteps to the next sibling for which all children are explored. The second optionis to explore first all the siblings and when no sibling exist, explore thechildren. This is important to understand. If two elements exist with the samename, the result of both variants can differ. Consider the following XMLstream

<Order><billing address><City>Cary</City><Country>America</Country></billing address><shipping address><City>Hursley</City><Country>United Kingdom</Country></shipping address></Order>

Represented as a tree, you would have the following tree representation:

154 Business Integration Solutions with MQSeries Integrator

Figure 104. Tree representation for a message with two occurrences of an element

In a depth-first traversal, the order in which nodes are visited is 1-2-3-4-5-6-7.With the other algorithm, the order would be 1-2-5-6-7-3-4. Thus, for thedepth-first variant, you hit first the element Country with the value “America”,while for the other variant this will be the element with the value “UnitedKingdom”.

Now that we understand the tree traversal mechanism, let’s see how this canbe accomplished. Starting with the element that was received as anargument, we retrieve the name of that element by using the utility functioncniElementName. We compare it with the name argument and if it is equal,we jump out of the function. If it isn’t equal we get the first child (remember,depth-first) of the element and use it as the argument for a recursive call tofindElementName. If the result of the recursion is non-zero, then we havefound the element with the requested name and we jump out of the function.If not, we use the utility function cniNextSibling and pass the result to anotherrecursive call to findElementName. For the second variant of tree traversal,the order of the recursive calls would be the other way round.

"Hursley"Value

CityName

"United Kingdom"Value

CountryName

"Cary"Value

CityName

"America"Value

CountryName

OrderName

XMLName

1

3 4 6 7

Billing AddressName

Shipping AddressName

2 5

Chapter 7. Developing your own plug-in 155

CciElement* findElementName(CciElement* element,CciChar* name,NODE_CONTEXT_ST* nc

){static int depth = -1;CciElement* firstChild = 0;CciElement* nextSibling = 0;CciElement* currentElement = 0;int rc = 0;CciChar elementName[256];

if (element != 0) {cniElementName(&rc, element, (CciChar*)&elementName,

sizeof(elementName));

if (wcscmp(elementName, name) == 0){return element;

}firstChild = cniFirstChild(&rc, element);

if (firstChild) {depth++;currentElement = findElementName(firstChild, name, nc);if (currentElement) {return currentElement;

}}

nextSibling = cniNextSibling(&rc, element);if (nextSibling) {currentElement = findElementName(nextSibling, name, nc);if (currentElement) {return currentElement;

}}else {depth--;

}}else {depth--;

}return 0;

}

156 Business Integration Solutions with MQSeries Integrator

7.4 Testing the plug-in during development

To test and debug the Switch node, we created a simple message flow with aMQInput node and MQOutput nodes for each possible output terminal. Themessage flow is shown in Figure 105.

Figure 105. Message flow to test the Switch node

As explained before, when debugging a message flow, it is helpful to connectall terminals, even those that you do not expect to be used. Each MQOutputnode is linked with its own MQSeries queue. The MQInput node is configuredfor generic XML messages by specifying the XML value in the MessageDomain entry field. For the plug-in it should not matter what kind of messageis coming in. An MRM-defined message with a field called Country wouldwork fine too.

Chapter 7. Developing your own plug-in 157

The configuration of the Switch node is reasonably simple, as shown inFigure 106:

Figure 106. Configuration of the CountrySwitch node

To drive the message flow, we used the standard MQSeries sample programamqsput. In the next figure you see some sample XML messages that wereused to test the plug-in. The fifth message ends up in the SWITCH_FAILUREqueue because Belgium is not one of the accepted values for the elementCountry. The fourth message ends up in the SWITCH_FAILURE queue toobecause there is no element with the name Country. All other messages arerouted to the AMERICA queue.

C:\>amqsput COUNTRYSample AMQSPUT0 starttarget queue is COUNTRY<Message><City>Cary</City><Country>America</Country></Message><Country>America</Country><Message><Country>America</Country></Message><Request><Type>America</Type></Request><Message><Country>Belgium</Country><City>Cary</City></Message><Message><Country>America</Country><City>Cary</City></Message>

158 Business Integration Solutions with MQSeries Integrator

With the configuration of the Switch node, shown in Figure 106 the resultingtrace file contains the following output:

NODE: <SwitchNode> -> _evaluate() context=0xae20400NODE: <SwitchNode> _evaluate() context=0xae20400 returncode cniLastChild : 0NODE: <SwitchNode> _evaluate() context=0xae20400 returncode cniElementName : 0NODE: <SwitchNode> _evaluate() context=0xae20400 elementName : XMLNODE: <SwitchNode> _evaluate() context=0xae20400 returncode cniFirstChild : 0NODE: <SwitchNode> -> findElementName() context=0xae20400 elementName : CountryNODE: <SwitchNode> findElementName() context=0xae20400 returncodecniElementName : 0NODE: <SwitchNode> findElementName() context=0xae20400 elementName : MessageNODE: <SwitchNode> findElementName() context=0xae20400 returncodecniFirstChild : 0NODE: <SwitchNode> -> findElementName() context=0xae20400 elementName : CountryNODE: <SwitchNode> findElementName() context=0xae20400 returncodecniElementName : 0NODE: <SwitchNode> findElementName() context=0xae20400 elementName : CityNODE: <SwitchNode> findElementName() context=0xae20400 returncodecniFirstChild : 0NODE: <SwitchNode> -> findElementName() context=0xae20400 elementName : CountryNODE: <SwitchNode> findElementName() context=0xae20400 returncodecniElementName : 0NODE: <SwitchNode> findElementName() context=0xae20400 elementName :NODE: <SwitchNode> findElementName() context=0xae20400 returncodecniFirstChild : 0NODE: <SwitchNode> <- findElementName() context=0xae20400NODE: <SwitchNode> -> findElementName() context=0xae20400 elementName : CountryNODE: <SwitchNode> findElementName() context=0xae20400 returncodecniElementName : 0NODE: <SwitchNode> findElementName() context=0xae20400 elementName : CountryNODE: <SwitchNode> <- findElementName() context=0xae20400NODE: <SwitchNode> <- findElementName() context=0xae20400NODE: <SwitchNode> _evaluate() context=0xae20400 returncodecniElementCharacterValue: 0NODE: <SwitchNode> _evaluate() context=0xae20400 elementValue : AmericaNODE: <SwitchNode> -> getOutputTerminalHandle() context=0xae20400 terminalName :AmericaNODE: <SwitchNode> <- getOutputTerminalHandle() context=0xae20400 matchedNODE: <SwitchNode> _evaluate() context=0xae20400 message propagatedNODE: <SwitchNode> <- _evaluate() context=0xae20400

The above output is generated for the first message in the test session. Itstarts by entering the implementation function _evaluate. Then you see thereturn code for the utility functions cniLastChild and cniElementName. As youcan see on the next line, the name of the last child of a message is XML, themessage domain. We then call the utility function cniFirstChild to find the rootelement of the XML message, which is Message. Evaluate calls then the

Chapter 7. Developing your own plug-in 159

internal function findElementName to traverse the message tree until it findsan element with name Country. The traverse algorithm is depth-first. Thefunction calls itself recursively until it detects that the element City has nochildren. The function returns to the previous level where it calls the utilityfunction cniNextSibling (not traced). The function calls itself again with theresult of cniNextSibling as an argument. That element appears to have thename we were looking for and thus the function is returning to the originalcaller, _evaluate. That function calls the utility functioncniElementCharacterValue to get the value associated with the elementCountry. This is America and thus we look for the handle of the outputterminal America. We finally propagate the message to this output terminal,which is the end of the _evaluate function.

To have even more tracing available, especially during the initialization phaseof the lil, we used some compiler directives to include more print-outs whenusing the debug version of the lil module. The output of this early phase goesto a file whose name is hard coded in the source. The output of this file givesa good understanding about what happens in this early phase. Tracing startsas soon as possible during the execution of the functioncniCreateNodeContext. This function creates the structure to hold theattributes and calls the cniSetAttribute function to specify the default values.Next, the cniCreateNodeContext function builds the list of input and outputterminals. Finally, the cniCreateNodeContext displays some environmentinformation that was obtained by calling the utility function cniGetBrokerInfo.

Tracing continues then with a number of cniSetAttribute calls to specify valuesfor the inherited attributes and for our own configurable attributes. When thename of the attribute nodeTraceOutFile changes, the current trace file isclosed and tracing continues in the output file that was requested.

NODE: <SwitchNode> -> insAttrTblEntry() context=0xae51e80 attrName='nodeTraceOutfile'NODE: <SwitchNode> <- insAttrTblEntry() context=0xae51e80NODE: <SwitchNode> -> insAttrTblEntry() context=0xae51e80 attrName='nodeTraceSetting'NODE: <SwitchNode> <- insAttrTblEntry() context=0xae51e80NODE: <SwitchNode> -> _setAttribute() context=0xae51e80 attrName='nodeTraceOutfile'attrValue='C:\SwitchNode.trc'NODE: <SwitchNode> -> handleChangedTraceFile() context=0xae51e80attrValue='C:\SwitchNode.trc'NODE: <SwitchNode> <- handleChangedTraceFile() context=0xae51e80 closing current tracefileNODE: <SwitchNode> <- handleChangedTraceFile() context=0xae51e80NODE: <SwitchNode> <- _setAttribute() rc=0NODE: <SwitchNode> -> _setAttribute() context=0xae51e80 attrName='nodeTraceSetting'attrValue='1'NODE: <SwitchNode> -> handleChangedTraceSetting() context=0xae51e80NODE: <SwitchNode> -> _getAttribute() context=0xae51e80 attrName='nodeTraceOutfile'

160 Business Integration Solutions with MQSeries Integrator

NODE: <SwitchNode> <- _getAttribute() rc=0NODE: <SwitchNode> <- handleChangedTraceSetting() context=0xae51e80NODE: <SwitchNode> <- _setAttribute() rc=0NODE: <SwitchNode> -> insInputTerminalListEntry() context=0xae51e80 terminalName='in'NODE: <SwitchNode> <- insInputTerminalListEntry() context=0xae51e80NODE: <SwitchNode> -> insOutputTerminalListEntry() context=0xae51e80terminalName='America'NODE: <SwitchNode> <- insOutputTerminalListEntry() context=0xae51e80NODE: <SwitchNode> -> insOutputTerminalListEntry() context=0xae51e80terminalName='Denmark'NODE: <SwitchNode> <- insOutputTerminalListEntry() context=0xae51e80NODE: <SwitchNode> -> insOutputTerminalListEntry() context=0xae51e80terminalName='United Kingdom'NODE: <SwitchNode> <- insOutputTerminalListEntry() context=0xae51e80NODE: <SwitchNode> -> insOutputTerminalListEntry() context=0xae51e80terminalName='failure'NODE: <SwitchNode> <- insOutputTerminalListEntry() context=0xae51e80NODE: <SwitchNode> -> displayEnvironment() context=0xae51e80NODE: <SwitchNode> -> displayEnvironment() context=0xae51e80 calling cniGetBrokerInfo

Broker Name : 'MQSI'Execution Group : 'default'Message Flow : 'SwitchTest'MQ Queue Manager : 'MQSI'

NODE: <SwitchNode> <- displayEnvironment() context=0xae51e80NODE: <SwitchNode> -> _setAttribute() context=0xae51e80 attrName='userTraceLevel'attrValue='none'NODE: <SwitchNode> <- _setAttribute() rc=1NODE: <SwitchNode> -> _setAttribute() context=0xae51e80 attrName='traceLevel'attrValue='none'NODE: <SwitchNode> <- _setAttribute() rc=1NODE: <SwitchNode> -> _setAttribute() context=0xae51e80 attrName='userTraceFilter'attrValue='none'NODE: <SwitchNode> <- _setAttribute() rc=1NODE: <SwitchNode> -> _setAttribute() context=0xae51e80 attrName='traceFilter'attrValue='none'NODE: <SwitchNode> <- _setAttribute() rc=1NODE: <SwitchNode> -> _setAttribute() context=0xae51e80 attrName='label'attrValue='CountrySwitch'NODE: <SwitchNode> <- _setAttribute() rc=1NODE: <SwitchNode> -> _setAttribute() context=0xae51e80 attrName='nodeTraceOutfile'attrValue='C:\ConfiguredTraceFile.txt'NODE: <SwitchNode> -> handleChangedTraceFile() context=0xae51e80attrValue='C:\ConfiguredTraceFile.txt'NODE: <SwitchNode> <- handleChangedTraceFile() context=0xae51e80 closing current tracefile

At this point the tracing continues in the trace file that was configured in themessage flow. The following trace entries are copied from that file. The last

Chapter 7. Developing your own plug-in 161

line starts with the first call to the function evaluate(). From that point ontracing is identical with what has been discussed before.

NODE: <SwitchNode> <- handleChangedTraceFile() context=0xae51e80NODE: <SwitchNode> <- _setAttribute() rc=0NODE: <SwitchNode> -> _setAttribute() context=0xae51e80 attrName='nodeTraceSetting' attrValue='1'NODE: <SwitchNode> -> handleChangedTraceSetting() context=0xae51e80NODE: <SwitchNode> <- handleChangedTraceSetting() context=0xae51e80NODE: <SwitchNode> <- _setAttribute() rc=0NODE: <SwitchNode> -> _evaluate() context=0xae51e80

7.5 Summary

In this chapter, we have explored the powerful framework of MQSeriesIntegrator to extend its functionality with user-written functionality. We’veshown how to integrate this functionality into the product. Finally, we haveanalyzed the implementation of a simple Switch node. We went through theimplementation of the important functions and showed some techniques toassist in debugging your own node.

162 Business Integration Solutions with MQSeries Integrator

Part 2. A Business Integration solution

The second part of the book looks at a solution with MQSeries, MQSeriesIntegrator, WebSphere, and DB2. This solution consists of a Web applicationthat finds information about a customer on a number of separate systems.We’ve called this solution single customer view. While we are aware that theissue of getting a single customer view is far more complex than what isshown here, this solution will help customers in architecting their solution forgetting a single customer view. Basically, the solution shows how to break upa single request into multiple requests, using MQSeries Integrator, and howto reformat each part of the request into the format that the back-officeapplication expects. Finally, we show how each reply is collected and used tobuild a single reply for the front-end application.

© Copyright IBM Corp. 2000 163

164 Business Integration Solutions with MQSeries Integrator

Chapter 8. Getting a single customer view with MQSeries

This section shows how MQSeries and MQSeries Integrator can be used toenable the gathering of information from multiple MQSeries-enabled legacysystems and then display this information on a single Web page. Figure 107is a high-level view of the components of the solution.

Figure 107. Component overview

The environment used for development of this application solution consistedof two Netfinity 3000 workstations running Windows NT Workstation V4.0. Alist of hardware and software used for this example can be found in AppendixA, “Hardware and software specification” on page 225.

The remainder of this chapter will address the MQSeries and MQSeriesIntegrator configurations built for the solution. It is expected that you arealready familiar with installing and configuring MQSeries for Windows/NT sono detailed information on this task is included. Please see Chapter 2,“Installation and configuration” on page 21 for information on installingMQSeries Integrator V2.0. Information on installing and implementing theother software components in the solution is outside the scope of thisredbook.

© Copyright IBM Corp. 2000 165

8.1 Single customer view as an e-business pattern

To assist customers in the development of e-business solutions, IBM hasdeveloped materials that describe some typical scenarios or patterns in whichmost of the e-business solutions fit.

The first way of describing a e-business solution is based on the businesspattern. Five patterns have been recognized:

1. User-to-Business

2. User-to-Online Buying

3. Business-to-Business

4. User-to-Data

5. User-to-User

The solution we will describe in this chapter fits in the User-to-BusinessPattern.

The next view of an e-business solution is the Logical Application topology,which is defined as the way to configure the interaction between users,applications and data. Two types are recognized. The first topology includesno interaction with back-end systems. The second topology includes anapplication that interacts synchronously or asynchronously with back-endsystems.

Please refer to the following Web site for the latest status of this project:http://www-4.ibm.com/software/developer/web/patterns/

8.2 Outbound Flow

This section describes the outbound flow of the request message from theWeb page to the legacy back-end programs. There is a main flow,RB_SCV_1, and three sub-flows, RB_SCV_Request_Endow,RB_SCV_Request_House and RB_SCV_Request_Motor.

166 Business Integration Solutions with MQSeries Integrator

8.2.1 RB_SCV_1message flow

Figure 108. RB_SCV_1 message flow

This is the main outbound flow. Its purpose is to:

• Retrieve the request message(s).

• Determine if information exists for the identified customer

• Determine which back-end application(s) to send requests to

• Send a message to the Message Merger’s trigger queue to tell it howmany responses to expect and the message ID of the original request sothat the response messages can be associated with the correct requestmessage.

Chapter 8. Getting a single customer view with MQSeries 167

The flow was built by dragging the appropriate nodes from the list ofIBMPrimitives and then wiring them together. The properties of each of thenodes will be discussed in the order in which they appear in the flow, top tobottom, left to right, starting with the MQInput node SessReq. Only thesignificant nodes, those that transform the message or in some way affecthow it is processed, will be discussed in detail. The first time a type of node(for example, Compute node) is presented, a step-by-step review ofconfiguring the node will be covered. Subsequent instances of that node inthe flow will list only the configuration values.

Trace nodes and MQOutput nodes that are wired to Failure, Unknown orCatch terminals of the Compute or Filter nodes were defined and wired tofacilitate testing and debugging. You could implement this flow with none ofthe error type terminals wired, but then the failed message will end up in thequeue manager’s dead letter queue. Since MQSeries Integrator doesn’t putany feedback code in the dead letter header before it writes the messagethere, the only way to find out which node failed will be to review the messageflow, turn on the trace, and review the output. This can be tedious and timeconsuming so the recommendation is to wire all possible terminals during thedevelopment process.

8.2.1.1 SessReq MQInput nodeThe first node in the outbound flow is SessReq, an MQInput node. Itspurpose is to retrieve messages from the queue identified in the node’s Basictab and pass them on to the next node in the flow.

Figure 109. SessReq MQInput node: Basic tab

168 Business Integration Solutions with MQSeries Integrator

The Basic tab of the MQInput node identifies the name of the queue that willbe monitored for messages.

Figure 110. SessReq MQInput node: Default tab

Since the request message on the queue does not have an RFH header, theMessage Domain property of the MQInput node’s Default tab must be set toXML so that broker knows to use the built-in XML parser to parse themessage.

8.2.1.2 SessReqFail MQOutput nodeThis node receives messages that are propagated to the Failure terminal ofthe SessReq MQInput node. It writes them to the queue identified by thequeue manager and queue name specified on the node’s Basic tab.

Chapter 8. Getting a single customer view with MQSeries 169

Figure 111. SessReqFail MQOutput node

8.2.1.3 FilterRequest Filter nodeThe purpose of the FilterRequest Filter node is to determine if the customerrequested exists in the database. The single customer view sampleapplication uses a simple DB2 database to determine which types of policiesthe customer owns so that requests for information are only sent to theback-end applications where the customer has policy information. Theprimary reason for doing this is so that the inbound flow knows how manyresponses to expect but it would also lead to increased efficiency becauseunnecessary messages would be eliminated and back-end programs wouldonly be invoked if they contained information for the customer request.

170 Business Integration Solutions with MQSeries Integrator

Figure 112. FilterRequest Filter node

The ESQL shown in Figure 112 is a standard SQL construct to check if thecustomer number passed in the request message exists on the database.

If the customer number on the request message exists in the database themessage is propagated to the true node. In Figure 108 on page 167 you willnotice that if the message is propagated to the true terminal, it is actuallypassed to four nodes: FilterEndow, FilterHouse, FilterMotor andMergerTrigger. If the customer number doesn’t exist in the database, themessage is propagated to the false node, causing a failure message to bewritten to the reply-to queue identified on the request message.

8.2.1.4 FilterReqFail MQOutput nodeThis node receives the request message if processing fails in theFilterRequest Filter node. It writes the message to the queue identified by thequeue manager and queue name specified on the node’s Basic tab.

Chapter 8. Getting a single customer view with MQSeries 171

Figure 113. FilterReqFail MQOutput node

8.2.1.5 FilterReqUnknown MQOutput nodeThis node receives the request message if it is propagated to the Unknownterminal during processing in the FilterRequest Filter node. It writes themessage to the queue identified by the queue manager and queue namespecified on the node’s Basic tab.

Figure 114. FilterReqUnknown MQOutput node

8.2.1.6 NoInfo Compute nodeThe request message is passed to this node when it is propagated to thefalse terminal of the FilterRequest Filter node. A request would bepropagated to the false terminal if the customer number on the request

172 Business Integration Solutions with MQSeries Integrator

message does not exist on the SCV_Policy DB2 database table. Themessage is augmented with a return code and propagated to the outputterminal.

Figure 115. NoInfo Compute node

Since we want topass the originalmessage we selectCopy entiremessage.

Chapter 8. Getting a single customer view with MQSeries 173

Figure 116. NoInfo Compute node ESQL

8.2.1.7 NoPolicyInfo MQReply nodeThis node writes the message passed to it to the reply-to queue identified inthe message header.

The first line of ESQLis generated for usbecause the Copyentire message wasselected.

The second line wasinserted manually toadd an additionalfield, ReturnCode, tothe message before itis propagated to thenode’s outputterminal.

174 Business Integration Solutions with MQSeries Integrator

8.2.1.8 FilterEndow Filter node

Figure 117. Node: FilterEndow

The purpose of the FilterEndow node is to determine if Endowment policyinformation exists for the customer. In Figure 108 on page 167 you will noticethat the false terminal is not wired. If no Endowment policy information existsfor this customer, message processing for this leg of the flow is abandoned. Ifinformation does exist on the database for this customer the message ispropagated to the true terminal, which is wired to a sub-flow calledRB_SCV_Request_Endow. This sub-flow is discussed in 8.2.2,“RB_SCV_Request_Endow message flow” on page 188.

8.2.1.9 FilterEndowFail MQOutput nodeThis node receives a request message that fails processing in theFilterEndow node and has been propagated to the Failure terminal of thatnode. It writes the message to the queue identified by the queue managerand queue name specified on the node’s Basic tab.

Chapter 8. Getting a single customer view with MQSeries 175

Figure 118. FilterEndowFail MQOutput node

8.2.1.10 FilterEndowUnknown nodeThis node receives a request message that fails processing in theFilterEndow node and has been propagated to the Failure terminal of thatnode. It writes the message to the queue identified by the queue managerand queue name specified on the node’s Basic tab.

Figure 119. FilterEndowUnknown MQOutput node

8.2.1.11 RB_SCV_Request_Endow1This is actually the connection to a sub-flow, RB_SCV_Request_Endow. Ithas no properties. You add the flow to the palette by dragging onto the palettefrom the list of message flows on the left hand side of the window. Because

176 Business Integration Solutions with MQSeries Integrator

the sub-flow has been created with an Input Terminal node, there will be aninput terminal on the icon that you can then wire to (an output terminal of)another node in the flow. In this sample application, the true terminal of theFilterEndow Filter node is wired to the input terminal of this sub-flow so therequest message will be passed. The nodes that comprise this sub-flow aredescribed in 8.2.2, “RB_SCV_Request_Endow message flow” on page 188.

8.2.1.12 FilterHouse Filter nodeThe purpose of the FilterHouse node is to determine if House policyinformation exists for the customer. In Figure 108 on page 167 you will noticethat the false terminal is not wired. If no House policy information exists forthis customer, message processing for this leg of the flow is abandoned. Ifinformation does exist on the database for this customer the message ispropagated to the true terminal, which is wired to a sub-flow calledRB_SCV_Request_House.

Figure 120. FilterHouse Filter node

8.2.1.13 FilterHouseFail MQOutput nodeThis node receives a request message that fails processing in the FilterHousenode and has been propagated to the Failure terminal of that node. It writesthe message to the queue identified by the queue manager and queue namespecified on the node’s Basic tab.

Chapter 8. Getting a single customer view with MQSeries 177

Figure 121. FilterHouseFail MQOutput node

8.2.1.14 FilterHouseUnknown MQOutput nodeThis node receives a request message that fails processing in the FilterHousenode and has been propagated to the Unknown terminal of that node. Itwrites the message to the queue identified by the queue manager and queuename specified on the node’s Basic tab.

Figure 122. FilterHouseUnknown MQOutput node

8.2.1.15 RB_SCV_Request_House1This is actually the connection to a sub-flow, RB_SCV_Request_House. Ithas no properties. You add the flow to the palette by dragging onto the palettefrom the list of message flows on the left hand side of the window. Becausethe sub-flow has been created with an Input Terminal node, there will be an

178 Business Integration Solutions with MQSeries Integrator

input terminal on the icon that you can then wire to (an output terminal of)another node in the flow. In this sample application, the true terminal if theFilterHouse Filter node is wired to the input terminal of this sub-flow so therequest message will be passed. The nodes that comprise this sub-flow aredescribed in 8.2.3, “RB_SCV_Request_House message flow” on page 210.

8.2.1.16 FilterMotor Filter nodeThe purpose of the FilterMotor node is to determine if Motor policyinformation exists for the customer. In Figure 108 on page 167 you will noticethat the false terminal is not wired. If no Motor policy information exists forthis customer, message processing for this leg of the flow is abandoned. Ifinformation does exist on the database for this customer the message ispropagated to the true terminal, which is wired to a sub-flow calledRB_SCV_Request_Motor.

Figure 123. FilterMotor Filter node

8.2.1.17 FilterMotorFail MQOutput nodeThis node receives a request message that fails processing in the FilterHousenode and has been propagated to the Failure terminal of that node. It writesthe message to the queue identified by the queue manager and queue namespecified on the node’s Basic tab.

Chapter 8. Getting a single customer view with MQSeries 179

Figure 124. FilterMotorFail MQOutput node

8.2.1.18 FilterMotorUnknown MQOutput nodeThis node receives a request message that fails processing in the FilterHousenode and has been propagated to the Unknown terminal of that node. Itwrites the message to the queue identified by the queue manager and queuename specified on the node’s Basic tab.

Figure 125. FilterMotorUnknown MQOutput node

8.2.1.19 RB_SCV_Request_Motor1This is actually the connection to a sub-flow, RB_SCV_Request_Motor. It hasno properties. You add the flow to the palette by dragging onto the palettefrom the list of message flows on the left hand side of the window. Becausethe sub-flow has been created with an Input Terminal node, there will be an

180 Business Integration Solutions with MQSeries Integrator

input terminal on the icon that you can then wire to (an output terminal of)another node in the flow. In this sample application, the true terminal if theFilterMotor Filter node is wired to the input terminal of this sub-flow so therequest message will be passed. The nodes that comprise this sub-flow aredescribed in 8.2.4, “RB_SCV_Request_Motor message flow” on page 213.

8.2.1.20 MergerTrigger Compute nodeThe MergerTrigger Compute node creates a “trigger” message for the Javaapplet MessageMerger. This trigger message tells MessageMerger howmany response messages to expect and the correlation ID of thosemessages so that it can match up the back-end response messages to theoriginal request message.

Figure 126. MergerTrigger Compute node

Input to this node is the DB2 database table SCV_Policy. This datasource isadded by clicking the Add button and then filling in the Data source and Tablename variables. The output from this node is a pre-defined message,SCV_MM_Trigger_Msg in MRM message set SCV_MSet. Since the outputmessage looks nothing like the input message, we select Copy messageheaders only.

Chapter 8. Getting a single customer view with MQSeries 181

Figure 127 shows the ESQL for the MergerTrigger Compute node. Note thatthe ESQL generated by the Copy message headers only option are “scrolledoff” the top of the window and not shown.

Figure 127. MergerTrigger Compute node ESQL

The first three of the four lines marked in Figure 127 set the properties for thenew message. Since the incoming request message is XML and the outputmessage is a legacy format we need to tell the broker how to parse the newmessage.

182 Business Integration Solutions with MQSeries Integrator

Figure 128. MergerTrigger Compute node ESQL, contd.

The ESQL statements marked in Figure 128 declare two integer variables foruse in determining the number of policies of a given type that exist for thecustomer (J) and how many types of policy exist for the customer (K). The (K)variable is initialized to zero and will be incremented by one for each policytype that exists.

Figure 129. MergerTrigger Compute node ESQL, contd.

Chapter 8. Getting a single customer view with MQSeries 183

The lines of ESQL marked in Figure 129 interrogate the database todetermine if any “HOUSE” policies exist for the customer. If any policies existthen the policy type counter (K) is incremented by 1.

Figure 130. MergerTrigger Compute node ESQL, contd.

The lines of ESQL marked in Figure 130 interrogate the database todetermine if any “ENDOW” policies exist for the customer. If any policies existthen the policy type counter (K) is incremented by 1.

184 Business Integration Solutions with MQSeries Integrator

Figure 131. MergerTrigger Compute node ESQL, contd.

The lines of ESQL marked in Figure 131 interrogate the database todetermine if any “MOTOR” policies exist for the customer. If any policies existthen the policy type counter (K) is incremented by 1.

Figure 132. MergerTrigger Compute node ESQL, contd.

The final line of ESQL in the MergerTrigger Compute node sets theSCV_PolicyCountStr_ID field in the output message to the value of (K). As

Chapter 8. Getting a single customer view with MQSeries 185

the preceding ESQL has been executed, (K) gets incremented for each policytype that exists for the customer. This correlates to the number of back-endrequests for information that will be sent.

8.2.1.21 MergerTriggerFail MQOutput nodeThis node receives a request message that fails processing in theMergerTrigger Compute node and has been propagated to the Failureterminal of that node. It writes the message to the queue identified by thequeue manager and queue name specified on the node’s Basic tab.

Figure 133. MergerTriggerFail MQOutput node

8.2.1.22 MergerTriggerTrace Trace nodeThis node is used to show what the message being passed looks like at thispoint in the flow. It’s used for debugging purposes. For a discussion onconfiguring a Trace node please see 8.2.2.4, “RequestEndowTrace Tracenode” on page 205.

186 Business Integration Solutions with MQSeries Integrator

Figure 134. MergerTriggerTrace Trace node

8.2.1.23 MergerTriggerQ MQOutput nodeThis MQOutput node parses the message according to the properties set inthe MergerTrigger Compute node and writes the message to the queueidentified by the queue manager and queue specified on the node’s Basic tab.

Figure 135. MergerTriggerQ MQOutput node

Chapter 8. Getting a single customer view with MQSeries 187

8.2.2 RB_SCV_Request_Endow message flow

Figure 136. Flow RB_SCV_Request_Endow

The purpose of this “sub-flow” is to augment the request message withinformation from the database and then reformat it from XML into a formatthat is expected by the legacy back-end program.

8.2.2.1 InputTerminal1 Input Terminal nodeThis node has no properties. Its purpose is to provide an input terminal to theRB_SCV_Request_Endow sub-flow. This is how the main flow, RB_SCV_1passes the request message to the sub-flow.

188 Business Integration Solutions with MQSeries Integrator

8.2.2.2 RequestEndow Compute node

Figure 137. Node: RequestEndow

The node in Figure 137 was created by dragging a Compute node onto thepalette and setting the appropriate properties. The following figures show thesteps taken.

After dragging a Compute node onto the palette, right-click the node imageand select the Properties pull-down.

Figure 138. The Compute node Properties pull-down menu

A DB2 database,SCV_Policy, is inputto this node (inaddition to themessage passed to itfrom the main flowRB_SCV_1)

Only the messageheaders have beencopied

The output messageis defined in the MRM

Chapter 8. Getting a single customer view with MQSeries 189

Figure 139. Copying messasge headers only

First select Copy message headers only. This causes the message headerinformation but no message data to be copied from the input format to theoutput format. Since the output message is completely different from the inputmessage we only want the GUI to prefill the header information in the outputmessage.

190 Business Integration Solutions with MQSeries Integrator

Figure 140. The Compute node add input task

The next step is to add input information to the Compute node. To do this weclick the Add button on the Inputs side of the box.

Chapter 8. Getting a single customer view with MQSeries 191

Figure 141. Adding input sources to a Compute node

Clicking the Add button causes the Add pop-up window to appear. It isprefilled with message set information from the Message Repository Manager(MRM). Since our input is going to be a database we select the Databasetable option instead and click the OK button.

192 Business Integration Solutions with MQSeries Integrator

Figure 142. Adding a database table as a Compute node input source

The Data Source and Table Name fields do not get prefilled by MQSeriesIntegrator. You must know the names of the database and table that are goingto be used as input to this Compute node.

Select a databasetable instead of amessage by clickingon the databasetable selectionbutton.

Chapter 8. Getting a single customer view with MQSeries 193

Figure 143. Entering the data source and table names to the Compute node input

In the case of the single customer view sample application, the database weare using is named SCV and the table name is SCV_Policy so we type thosein and click OK.

Type in the names ofthe Data Source(database name) andTable name and clickon the OK button toadd this externaldatabase table as aninput data source tothe compute module.

194 Business Integration Solutions with MQSeries Integrator

Figure 144. Selecting the MRM output message of the Compute node

Defining an external database as input is now complete. The output messageformat required by the legacy back-end program has already been defined tothe Message Repository Manager so all we have to do is select it. We startthe selection process by clicking the Add button on the Output Messagesside of the box.

Click on the Addbutton to select anoutput message fromthe MessageRepository Manager

Chapter 8. Getting a single customer view with MQSeries 195

Figure 145. Selecting an MRM message as the output of the Compute node

Clicking the Add button causes the Add pop-up window to appear. It isprefilled with message set information from the Message Repository Manager(MRM). Since we have only one message set defined in the MRM, the correctmessage set is displayed by default but we have multiple messages in themessage set and we want to select a different one. Open the drop-down boxto get a list of available messages.

196 Business Integration Solutions with MQSeries Integrator

Figure 146. Selecting a Compute node output message from the MRM

Since this message flow is sending a message to the Endowment legacyback-end program we select the SCV_ENDOW_BACKEND_MSG_ID.

Select the desiredmessage byhighlighting the listentry and clicking theOK button.

Chapter 8. Getting a single customer view with MQSeries 197

Figure 147. Compute node with inputs and outputs selected

Figure 147 shows what the Compute node looks like so far. SCV_Policy hasbeen selected as an input source. The output message is theSCV_ENDOW_BACKEND_MESSAGE from the MRM. We have also selectedto copy message headers only. The next step is to start entering the ESQLrequired to generate the message to be sent to the legacy back-end program.Start this process by clicking the ESQL tab.

Start the process ofcustomizing the ESQLby clicking the ESQLtab.

198 Business Integration Solutions with MQSeries Integrator

Figure 148. Compute node, generated ESQL

When you first see the ESQL palette, you’ll notice that there is already someESQL in place. This was generated by selecting Copy message headersonly on the previous panel. We add the ESQL statements to populateSCV_ENDOW_BACKEND_MSG following the pregenerated ESQLstatements.

This ESQL isgenerated for you. Itcauses the messageheaders to be copiedfrom the inputmessage to theoutput message.

Chapter 8. Getting a single customer view with MQSeries 199

Figure 149. ESQL to populate SCV_ENDOW_BACKEND_MSG properties

The three lines selected in Figure 149 set the properties of the new message.This is required because the incoming message did not have an RFH header.The MessageSet, MessageType and MessageFormat properties are used bythe MRM parser to format the output message.

200 Business Integration Solutions with MQSeries Integrator

Figure 150. ESQL to populate SCV_ENDOW_BACKEND_MSG MQMD

The two lines highlighted in Figure 150 set the MQSeries Message Descriptor(MQMD) properties. This is where we tell the legacy back-end program thename of the reply-to queue.

Chapter 8. Getting a single customer view with MQSeries 201

Figure 151. Compute node simple EQSL

The next two lines, selected in Figure 151, are simple ESQL statements to setfield values in the output message. The first statement selected shows settinga literal value. The second statement shows setting the output message fieldto a value from the input message. You can see the results of thesestatements in the output from the Trace node shown on page 208.

202 Business Integration Solutions with MQSeries Integrator

Figure 152. Calculating an output message field value

The statement selected in Figure 152 shows ESQL being used to count howmany rows exist on the external database for the customer number and policytype and then assigning that calculated value to one of the fields in the outputmessage. The CAST function is used because the output message fields areall STRING and the COUNT function returns an integer.

Chapter 8. Getting a single customer view with MQSeries 203

Figure 153. Using the Compute node ESQL to populate a list

The statement selected in Figure 153 selects all rows from the database thatmeet the criteria (customer number and policy type) and populate a repeatingstructure (SCV_Policy_No_Id) with the returned row(s).

204 Business Integration Solutions with MQSeries Integrator

Figure 154. Initializing unused repeating structure iterations

The repeating structure, SCV_Policy_No_Id, is a fixed array of 3. Thestatements selected in Figure 154 show filling the “unused” entries in thearray with spaces. We had previously determined how many rows of policyinformation exist (SCV_Policy_CountStr_Id) so we use this to determine theposition of the first “unused” entry in the array. We also know that the array isa fixed length of three entries so we can easily use a WHILE loop to initializethe remaining unused entries.

8.2.2.3 RequestEndowFail MQOutput nodeThis is an MQOutput node that receives the message if a failure occurs in theRequestEndow Compute node. The only significant properties are the queuemanager name and the queue name. These are entered on the node’s Basictab.

8.2.2.4 RequestEndowTrace Trace nodeThis node is used to show what the message being passed looks like at thispoint in the flow. It’s used for debugging purposes.

Chapter 8. Getting a single customer view with MQSeries 205

Figure 155. Configuring a Trace node

To configure a Trace node, you drag a Trace node from the primitives list tothe palette and select the Properties tab from the pop-up menu that isdisplayed when you right-click the Trace node icon you have just dragged tothe palette.

206 Business Integration Solutions with MQSeries Integrator

Figure 156. Configuring the Trace node: selecting the trace destination

The default destination of the trace output is the user trace log file. This is notthe best place to view the Trace node output as you will need to extract thelog, format it and then scan through potentially thousands of lines of output. Abetter choice is to output the Trace node data to a separate file. To do this youselect the file option from the destination pull-down menu as shown above.

Figure 157. Configuring the Trace node: identifying the destination file

The next step is to tell the broker where you want the Trace node output to besent. In Figure 157 we have specified that we want the Trace node data

Select the filedestination from thepull-down menu.

Name of file wheretrace data will bewritten.

Chapter 8. Getting a single customer view with MQSeries 207

written to a file named scvtrace. By default, the file will be created in the binsubdirectory of the directory where MQSeries Integrator is installed.

Next we need to tell the broker what to trace.

Figure 158. Configuring the Trace node: what to print in the trace

The pattern property is what tells the broker what to print to the trace file. Thesignificant statement in Figure 158 is the third line, ${Root}. This tells thebroker that the entire message should be written to the trace file. Thefollowing figures show what the broker writes to the trace file when theReqEndowTrace node is executed. Notice how the first two lines in thepattern are the first two lines in the trace, followed by the message andending with last line in the pattern box. The only statement in the pattern thatis necessary is the ${Root} but the rest of the text is descriptive informationthat identifies what you’re looking at and distinguishes between separatetrace entries written to the same trace file.

The date is 2000-04-19 Time is 06:45:53.888999The tree structure for the Request Endow output message looks like this...((0x1000000)Properties = ((0x3000000)MessageSet = 'DHQ6R5406U001'(0x3000000)MessageType = 'SCV_ENDOW_BACKEND_MSG_ID'(0x3000000)MessageFormat = 'CWF'(0x3000000)Encoding = 273(0x3000000)CodedCharSetId = 819(0x3000000)Transactional = TRUE(0x3000000)Persistence = FALSE

208 Business Integration Solutions with MQSeries Integrator

(0x3000000)CreationTime = GMTTIMESTAMP '2000-04-19 10:45:51.550'(0x3000000)ExpirationTime = -1(0x3000000)Priority = 0(0x3000000)Topic = NULL

)(0x1000000)MQMD = ((0x3000000)SourceQueue = 'SESSION.REQUEST.QUEUE'(0x3000000)Transactional = TRUE(0x3000000)Encoding = 273(0x3000000)CodedCharSetId = 819(0x3000000)Format = 'MQSTR'(0x3000000)Version = 2(0x3000000)Report = 0(0x3000000)MsgType = 1(0x3000000)Expiry = -1(0x3000000)Feedback = 0(0x3000000)Priority = 0(0x3000000)Persistence = 0(0x3000000)MsgId = X'414d51205343562020202020202020202389fd3813e00200'(0x3000000)CorrelId = X'000000000000000000000000000000000000000000000000'(0x3000000)BackoutCount = 0(0x3000000)ReplyToQ = 'SCV.ENDOW.BACKEND.REPLY.QUEUE'(0x3000000)ReplyToQMgr = 'SCV '(0x3000000)UserIdentifier = 'MUSR_MQADMIN'(0x3000000)AccountingToken =

X'16010515000000690da7498714117d6603bd07ed03000000000000000000000b'(0x3000000)ApplIdentityData = ' '(0x3000000)PutApplType = 28(0x3000000)PutApplName = 'MQSeries Client for Java '(0x3000000)PutDate = DATE '2000-04-19'(0x3000000)PutTime = GMTTIME '10:45:51.550'(0x3000000)ApplOriginData = ' '(0x3000000)GroupId = X'000000000000000000000000000000000000000000000000'(0x3000000)MsgSeqNumber = 1(0x3000000)Offset = 0(0x3000000)MsgFlags = 0(0x3000000)OriginalLength = 50

)(0x1000008)MRM = ((0x3000000)SCV_Backend_Program_Id = 'ENDOWMNT'(0x3000000)SCV_Customer_No_Id = '123456'(0x3000000)SCV_PolicyCountStr_ID = '1'(0x3000000)SCV_Policy_No_Id = '987654'(0x3000000)SCV_Policy_No_Id = ' '(0x3000000)SCV_Policy_No_Id = ' '

))End of Trace

Chapter 8. Getting a single customer view with MQSeries 209

8.2.2.5 EndowBackend MQOutput nodeThis MQOutput node parses the message according to the properties set inthe RequestEndow Compute node and writes the message to the queueidentified by the queue manager and queue specified on the node’s Basic tab.

8.2.3 RB_SCV_Request_House message flowThis message flow is a sub-flow of the RB_SCV_1 message flow. It augmentsthe request message passed to it with information from a DB2 database tableand reformats it into the format expected by the “House” legacy back-endprogram.

Figure 159. RB_SCV_Request_House message flow

210 Business Integration Solutions with MQSeries Integrator

8.2.3.1 RequestHouseIn Input Terminal nodeThis node has no properties. Its purpose is to provide an input terminal foranother message flow to pass a message to this flow.

8.2.3.2 RequestHouse Compute nodeThis node augments the request message with information from theSCV_Policy DB2 table and reformats the message from the XML format ofthe request message to the Custom Wire Format expected by the “House”legacy back-end program.

For step-by-step instructions on how to add a Compute node to a messageflow please see 8.2.2.2, “RequestEndow Compute node” on page 189.

As with the message created by the RB_SCV_Request_Endow messageflow, only message headers are copied from the original request message tothe new message created by this node to be sent to the “House” legacyback-end program. This is specified by clicking Copy message headersonly. This is shown in Figure on page 190.

Input to this node is the SCV_Policy DB2 database table. The same DataSource and Table Name used for the RequestEndow Compute node in theRB_SCV_Request_Endow message flow is used here. For step-by-stepinstructions on how to specify an input to a Compute node please refer to thetext and figures beginning on page 191.

Output from this node is message SCV_HOUSE_BACKEND_MSG inmessage set SCV_MSet. For step-by-step instructions on how to specify aninput to a Compute node please refer to the text and figures beginning onpage 196.

The ESQL in this node is exactly the same as the ESQL in the RequestEndowCompute node of the RB_SCV_Request_Endow message flow with a fewexceptions. In fact, the ESQL was copied from the RequestEndow Computenode and pasted into this one. The ESQL is shown in Figure 160. Theexceptions are indicated.

Chapter 8. Getting a single customer view with MQSeries 211

Figure 160. RequestEndow Compute node ESQL

8.2.3.3 ReqHouseFail MQOutput nodeThis node puts messages that fail during processing of the RequestHouseCompute node on the queue identified by the queue manager and queuename values specified on the node’s Basic tab.

Figure 161. ReqHouseFail MQOutput node

212 Business Integration Solutions with MQSeries Integrator

8.2.3.4 ReqHouseTrace Trace nodeThis Trace node prints the message to the destination specified in the Tracenode properties.

Figure 162. ReqHouseTrace Trace node

8.2.3.5 HouseBackend MQOutput nodeThis MQOutput node parses the message according the message’sproperties and writes it to the queue identified on the node’s Basic tab.

Figure 163. HouseBackend MQOutput node

8.2.4 RB_SCV_Request_Motor message flowThis message flow is a sub-flow of the RB_SCV_1 message flow. It augmentsthe request message passed to it with policy number information from a DB2database table, reformats the message, and writes it to the MQSeries queuemonitored by the Motor legacy back-end program.

Chapter 8. Getting a single customer view with MQSeries 213

Figure 164. RB_SCV_Request_Motor message flow

8.2.4.1 RequestMotorIn Input Terminal nodeThis node has no properties. Its purpose is to provide an input terminal to theflow so that a message can be passed in from another flow.

8.2.4.2 RequestMotor Compute nodeThis node uses information extracted from the SCV DB2 databaseSCV_Policy table to augment the request message with a list of policynumbers to be retrieved. It also reformats the message from XML to acustomer wire format expected by the legacy back-end program and writesthe message to the queue monitored by the Motor legacy back-end program.

For step-by-step instructions on how to add a Compute node to a messageflow please see 8.2.2.2, “RequestEndow Compute node” on page 189.

214 Business Integration Solutions with MQSeries Integrator

Figure 165. RequestMotor Compute node properties

As can be seen in the fields marked in Figure 165; only message headers arecopied from the input message to the output message, a DB2 database table,SCV_Policy is input to the Compute node and the output message is definedin the Message Repository Manager (MRM).

Chapter 8. Getting a single customer view with MQSeries 215

Figure 166. RequestMotor Compute node ESQL

The ESQL in this Compute node was copied from the RequestEndowCompute node and then the necessary changes were made to tailor thereferences for a Motor request. Figure 166 shows the values that werechanged when tailoring the ESQL.

8.2.4.3 ReqMotorFail MQOutput nodeThis node puts messages that fail during processing of the RequestMotorCompute node on a queue identified by the queue manager and queue namevalues specified on the node’s Basic tab.

216 Business Integration Solutions with MQSeries Integrator

Figure 167. ReqMotorFail MQOutput node

8.2.4.4 RequestMotorTrace Trace nodeThis Trace node prints the message to the destination specified in the Tracenode properties. The ${Root} statement specifies that the entire message isto be printed.

Figure 168. RequestMotorTrace Trace node

8.2.4.5 MotorBackend MQOutput nodeThis MQOutput node parses the message according to the properties set inthe RequestMotor Compute node and writes the message to the queueidentified by the queue manager and queue specified on the node’s Basic tab.

Chapter 8. Getting a single customer view with MQSeries 217

Figure 169. MQOutput node

8.3 Inbound flow

This section describes the inbound message flow.

1. The legacy back-end application writes its response message to thequeue name specified as the reply-to queue name in the requestmessage.

2. The response message is picked up by the RB_SCV_Backend_Replymessage flow or the RB_SCV_Backend_Reply_Endow message flow,depending on which legacy back-end application generated the reply.

- The RB_SCV_Backend_Reply message flow receives and processesmesages from the House and Motor legacy back-end applications.

- The RB_SCV_Backend_Reply_Endow message flow receives andprocesses messages from the Endow legacy back-end application.

3. The message flow parses the reply message and generates an outputmessage that consists of a subset of the fields on the input message withsemi-colon delimiters inserted between the fields in the output message.

4. The Message Merger Java application retrieves messages and “merges”messages having matching correlation IDs into a single message andwrites the merged message to a queue monitored by the ClientServletJava application.

5. The ClientServlet application retrieves the reply messages by correlationID and updates the Web page with the response data.

218 Business Integration Solutions with MQSeries Integrator

8.3.1 RB_SCV_Backend_Reply message flow

Figure 170. RB_SCV_Backend_Reply message flow

The RB_SCV_Backend_Reply message flow processes reply messages fromthe House and Motor legacy back-end applications. This flow demonstratesthat two separate queues are being monitored for reply messages from thetwo back-end applications and that the reply message, regardless of whichback-end application it came from (House or Motor), is being processed by asingle sub-flow, RB_SCV_Backend_Reply_House&Motor.

Chapter 8. Getting a single customer view with MQSeries 219

8.3.1.1 HouseBackendReply MQInput node

Figure 171. HouseBackendReply MQInput node default properties

The reply message sent by the House legacy back-end application does notcarry an RFH so the message properties must be set on the Default tab of theMQInput node. Figure 171 shows that the message is defined in the MRM,where the message set and message (type) and message format areidentified.

The Default tab of the MotorBackendReply is exactly the same.

8.3.1.2 RB_SCV_Backend_Reply_House&Motor nodeThis is a message processing node whose function is to pass the message toanother message flow. It has no properties.

8.3.1.3 BackendReplyFail MQOutput nodeThis node receives message propagated to the Failure terminal of theBackendReply MQInput node. It writes the message to the queue identifiedon the node’s Basic tab.

8.3.1.4 BackendReplyCatch nodeThis node receives message propagated to the Catch terminal of theBackendReply MQInput node. It writes the message to the queue identifiedon the node’s Basic tab.

220 Business Integration Solutions with MQSeries Integrator

8.3.2 RB_SCV_Backend_Reply_House&Motor message flow

Figure 172. RB_SCV_Backend_Reply_House&Motor message flow

This flow processes messages passed to it from theRB_SCV_Backend_Reply message flow.

8.3.2.1 BackendReply Input Terminal nodeThis node provides an input terminal into this flow. It has no properties.

8.3.2.2 FormatHouse&Motor Compute nodeThis node takes the reply message from the House and Motor legacyback-end applications, extracts the fields required for the output message,and inserts a semicolon delimiter between each of the fields in the outputmessage

Chapter 8. Getting a single customer view with MQSeries 221

.

Figure 173. FormatHouse&Motor Compute node

Input to this node is the reply message sent by either the House or the Motorlegacy back-end application. The input message is a legacy formatpre-defined in the MRM. It’s added to this node as input by clicking the Addbutton and selecting it from the drop-down list in the pop-up menu.

Output from this node is a predefined format expected by the Web front-endapplication. It too has been defined in the MRM and is added to the Computenode by clicking the Add button on the Output Messages side of the windowand selecting the appropriate message set and message from the drop-downlist in the pop-up menu.

Since the input and output messages are of different formats we select Copymessage headers only.

222 Business Integration Solutions with MQSeries Integrator

Figure 174. FormatHouse&Motor Compute node ESQL

The first five lines of ESQL are automatically generated because the Copymessage headers only option was selected.

Figure 175. FormatHouse&Motor Compute node ESQL

The next five lines are setting the message properties: the identification forthe message set and the name of the message type.

Figure 176. FormatHouse&Motor Compute node ESQL

This SET statement selects the policy information from the input messageand copies the values in the corresponding fields of the output message.

Chapter 8. Getting a single customer view with MQSeries 223

Figure 177. FormatHouse&Motor Compute node ESQL

This ESQL is filling in the delimiter between fields. For policy entries thatcontain real data, the delimiter is set to a semicolon. For empty entries it isset to blanks.

224 Business Integration Solutions with MQSeries Integrator

Appendix A. Hardware and software specification

A.1 Multi-broker setup

The three brokers ran on IBM Personal Computer 300PL machines. Eachmachine had a Pentium II processor running at 350 MHz and had 256 MBmemory on board.

The message producer and message consumer applications and queuemanagers ran on Netfinity 3000 machines with a Pentium II processor runningat 350 MHz and had 256 MB memory on board.

The User Manager and Configuration Manager were hosted on IBM ThinkPad600E machines, with a Pentium II processor running at 366 MHz with 224 MBmemory on board.

The AIX machine, used to host the Configuration Manager’s databases, wasa RS6000 43P Model 150, with a PowerPC processor running at 375 MHzand 128 MB real memory.

The Windows NT machines were running with the following software:

1. Windows NT Workstation V4 with ServicePac 5 applied

2. MQSeries V5.1 with CSD4 applied

3. MQSeries Integrator V2.0

4. DB2 UDB Enterprise Edition V6.1

The AIX box was running with the following software:

1. AIX V4.3

2. DB2 UDB Enterprise Edition V6.1

All computers were connected via a 16 Mbps token-ring network.

A.2 Single customer view application

This appendix lists the hardware and software used for the applicationsolution described in Chapter 8, “Getting a single customer view withMQSeries” on page 165.

The solution used two 350 MHz Pentium II IBM Netfinity 3000 servers. Oneserver hosted an IBM WebSphere Application Server and an IBM HTTPServer. The other server hosted MQSeries for Windows NT V5.1 and

© Copyright IBM Corp. 2000 225

MQSeries Integrator V2.0 in addition to the legacy programs and applicationdata. IBM DB2 UDB V6 was the database software used in the solution.TCP/IP was the communications protocol used. Details of the softwareinstalled on each server follow:

Server #1 - WebSphere

• IBM Netfinity 3000 350 MHz Pentium II

• 260 MB memory

• Windows NT Workstation V4.0 with ServicePac 5

• IBM HTTP Server V1.3.6

• IBM WebSphere Application Server V3.02

• IBM Java Development Kit V1.1.7

• IBM DB2 Universal Database (UDB) V6.1

• MQSeries Java Client V5.1

Server #2 - MQSeries

• IBM Netfinity 3000 350 MHz Pentium II

• 320 MB memory

• Windows NT Workstation V4.0 with ServicePac 5

• IBM MQSeries for Windows NT V5.1 with CSD04

• IBM MQSeries Integrator for Windows NT V2.0

• IBM DB2 Universal Database (UDB) V6.1

• IBM Java Development Kit V1.1.7

226 Business Integration Solutions with MQSeries Integrator

Appendix B. Source code for the SwitchNode plug-in

B.1 Header file SwitchNode.h/** Licensed Materials - Property of IBM* 5648-C63* (C) Copyright IBM Corp. 1999*/

#ifdef __cplusplusextern "C" {#endif

#include <BipCni.h>

#ifndef max#define max(x, y) (((x) > (y)) ? (x) : (y))#endif

#ifndef min#define min(x,y) (((x)<(y)) ? (x) : (y))#endif

#define MAX_ATTR_NAME_LEN 128#define MAX_NODE_NAME_LEN 128#define MAX_STRING_SIZE 256#define MAX_TERMINAL_NAME_LEN 256#define CNI_TYPE_INTEGER 1#define CNI_TYPE_STRING 2

#define CCI_CHECK_RC() \if (rc != CCI_SUCCESS) { \

if (rc == CCI_EXCEPTION) cciRethrowLastException(0); \else { \

cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "", L"MQSeriesIntegrator2", 0, "",0); \

return; \} \

}

typedef struct attributeTblEntry {void* next; /* Pointer to next entry */void* valptr; /* Pointer to value */int type; /* Value type */CciChar name[MAX_ATTR_NAME_LEN]; /* Attribute name */

} ATTRIBUTE_TBL_ENTRY;

typedef struct terminalListEntry {void* next; /* Pointer to next entry */CciTerminal* handle; /* Handle to terminal object */CciChar name[MAX_TERMINAL_NAME_LEN]; /* Terminal name */

} TERMINAL_LIST_ENTRY;

typedef struct context {CciNode* nodeObject; /* Handle for node object */ATTRIBUTE_TBL_ENTRY* attrListHead; /* Head of linked list of attributes */ATTRIBUTE_TBL_ENTRY* attrListPrevious; /* Previous entry in attribute list */TERMINAL_LIST_ENTRY* inputTerminalListHead; /* Head of linked list of input

terminal handles */

© Copyright IBM Corp. 2000 227

TERMINAL_LIST_ENTRY* inputTerminalListPrevious; /* Previous entry in input terminallist */TERMINAL_LIST_ENTRY* outputTerminalListHead; /* Head of linked list of output

terminal handles */TERMINAL_LIST_ENTRY* outputTerminalListPrevious; /* Previous entry in output terminal

list */int trace; /* Flag: Trace active? */FILE* tracefile; /* Trace file stream */CciChar nodeName[MAX_NODE_NAME_LEN]; /* Node name */

} NODE_CONTEXT_ST;

/* Function prototypes */

ATTRIBUTE_TBL_ENTRY *insAttrTblEntry(NODE_CONTEXT_ST* context,CciChar* attrName,int type

);

void *getInputTerminalHandle(NODE_CONTEXT_ST* context,CciChar* terminalName

);

TERMINAL_LIST_ENTRY *insInputTerminalListEntry(NODE_CONTEXT_ST* context,CciChar* terminalName

);

void *getOutputTerminalHandle(NODE_CONTEXT_ST* context,CciChar* terminalName

);

TERMINAL_LIST_ENTRY *insOutputTerminalListEntry(NODE_CONTEXT_ST* context,CciChar* terminalName

);

CciContext* _createNodeContext(CciFactory* factoryObject,CciChar* nodeName,CciNode* nodeObject

);

int _getAttributeName(CciContext* context,int index,CciChar* buffer,int bufsize

);

int _setAttribute(CciContext* context,CciChar* attrName,CciChar* attrValue

);

int _getAttribute(CciContext* context,CciChar* attrName,CciChar* buffer,int bufsize

228 Business Integration Solutions with MQSeries Integrator

);

void _evaluate(CciContext* context,CciContext* destinationList,CciContext* exceptionList,CciContext* message

);

#ifdef __cplusplus}#endif

B.2 Source file SwitchNode.c/** Licensed Materials - Property of IBM* 5648-C63* (C) Copyright IBM Corp. 1999*/

/******************************************************************************//* *//* Note: This sample plugin node implementation is not necessarily portable *//* to all platforms supported by MQSeries Integrator Version 2. *//* *//******************************************************************************/#include <windows.h>

/* Includes */#include <malloc.h>#include <memory.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <wchar.h>#include “SwitchNode.h”

/******************************************************************************//* *//* Plugin Node Utility function: *//* *//* Display the environment in which a node is running *//* *//******************************************************************************/void displayEnvironment(NODE_CONTEXT_ST* context

){static wchar_t* functionName=L”displayEnvironment()”;CNI_BROKER_INFO_ST broker_info_st;

if (context->tracefile) {fwprintf(context->tracefile, L”NODE: <%s> -> %s context=0x%x \n”,

context->nodeName, functionName, context);fflush(context->tracefile);

}

/* Setup the BROKER_INFO_ST to query our environment */memset(&broker_info_st, 0, sizeof(broker_info_st));broker_info_st.brokerName.buffer = malloc(MAX_STRING_SIZE);

Appendix B. Source code for the SwitchNode plug-in 229

broker_info_st.brokerName.bufferLength = MAX_STRING_SIZE;broker_info_st.executionGroupName.buffer = malloc(MAX_STRING_SIZE);broker_info_st.executionGroupName.bufferLength = MAX_STRING_SIZE;broker_info_st.messageFlowName.buffer = malloc(MAX_STRING_SIZE);broker_info_st.messageFlowName.bufferLength = MAX_STRING_SIZE;broker_info_st.queueManagerName.buffer = malloc(MAX_STRING_SIZE);broker_info_st.queueManagerName.bufferLength = MAX_STRING_SIZE;

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> -> %s context=0x%x calling cniGetBrokerInfo \n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

/* Get details about the broker environment */cniGetBrokerInfo(0,

((NODE_CONTEXT_ST *)context)->nodeObject,&broker_info_st);

if (context->tracefile) {fwprintf(context->tracefile,

L” Broker Name : ‘%s’\n”,broker_info_st.brokerName.buffer);

fwprintf(context->tracefile,L” Execution Group : ‘%s’\n”,broker_info_st.executionGroupName.buffer);

fwprintf(context->tracefile,L” Message Flow : ‘%s’\n”,broker_info_st.messageFlowName.buffer);

fwprintf(context->tracefile,L” MQ Queue Manager : ‘%s’\n”,broker_info_st.queueManagerName.buffer);

fflush(context->tracefile);}

/* Release storage */if (broker_info_st.brokerName.buffer)free(broker_info_st.brokerName.buffer);

if (broker_info_st.executionGroupName.buffer)free(broker_info_st.executionGroupName.buffer);

if (broker_info_st.messageFlowName.buffer)free(broker_info_st.messageFlowName.buffer);

if (broker_info_st.queueManagerName.buffer)free(broker_info_st.queueManagerName.buffer);

if (context->tracefile) {fwprintf(context->tracefile, L”NODE: <%s> <- %s context=0x%x \n”,

context->nodeName, functionName, context);fflush(context->tracefile);

}return;

}

/******************************************************************************//* *//* Plugin Node Utility function: *//* *//* Traverses the message tree, stops when it finds the first element with *//* the right name and returns the found element. It returns 0 if not found. *//* *//******************************************************************************/CciElement* findElementName(

230 Business Integration Solutions with MQSeries Integrator

CciElement* element,CciChar* name,NODE_CONTEXT_ST* nc

){static wchar_t* functionName=L”findElementName()”;static int depth = -1;CciElement* firstChild = 0;CciElement* nextSibling = 0;CciElement* currentElement = 0;int rc = 0;CciChar elementName[256];

if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> -> %s context=0x%x elementName : %s\n”,nc->nodeName, functionName, nc, name);

fflush(nc->tracefile);}

if (element != 0) {cniElementName(&rc, element, (CciChar*)&elementName, sizeof(elementName));if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x returncode cniElementName : %ld\n”,nc->nodeName, functionName, nc, rc);

fwprintf(nc->tracefile,L”NODE: <%s> %s context=0x%x elementName : %s\n”,nc->nodeName, functionName, nc, elementName);

fflush(nc->tracefile);}

if (wcscmp(elementName, name) == 0){return element;

}

firstChild = cniFirstChild(&rc, element);if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x returncode cniFirstChild : %ld\n”,nc->nodeName, functionName, nc, rc);

fflush(nc->tracefile);}

if (firstChild) {depth++;currentElement = findElementName(firstChild, name, nc);if (currentElement) {if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> <- %s context=0x%x\n”,nc->nodeName, functionName, nc);

fflush(nc->tracefile);}return currentElement;

}}nextSibling = cniNextSibling(&rc, element);if (nextSibling) {currentElement = findElementName(nextSibling, name, nc);if (currentElement) {if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> <- %s context=0x%x\n”,

Appendix B. Source code for the SwitchNode plug-in 231

nc->nodeName, functionName, nc);fflush(nc->tracefile);

}return currentElement;}

}else {depth--;

}}else {if (nc->tracefile) {fwprintf(nc->tracefile,

L”%s element is null pointer>\n”, functionName);fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x element is null pointer\n”,nc->nodeName, functionName, nc);

fflush(nc->tracefile);}depth--;

}

if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> <- %s context=0x%x\n”,nc->nodeName, functionName, nc);

fflush(nc->tracefile);}

return 0;}

/******************************************************************************//* *//* Plugin Node Utility function: *//* *//* Acquire storage for attribute and link to the context *//* *//******************************************************************************/ATTRIBUTE_TBL_ENTRY *insAttrTblEntry(NODE_CONTEXT_ST* context,CciChar* attrName,int type

){static wchar_t* functionName=L”insAttrTblEntry()”;ATTRIBUTE_TBL_ENTRY* entry;int attrSize;

#ifdef _DEBUGif (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> -> %s context=0x%x attrName=’%s’\n”,context->nodeName, functionName, context, attrName);

fflush(context->tracefile);}

#endif

entry = malloc(sizeof(ATTRIBUTE_TBL_ENTRY));if (entry) {entry->next = 0;entry->type = type;

switch (entry->type) {

232 Business Integration Solutions with MQSeries Integrator

case CNI_TYPE_INTEGER:attrSize = 4;break;

case CNI_TYPE_STRING:attrSize = MAX_STRING_SIZE;

default:/* Error: Invalid datatype */break;

}

/* Acquire and clear storage for attribute value */entry->valptr = malloc(attrSize);if (entry->valptr)memset(entry->valptr, 0, attrSize);

/* Store the attribute name */wcscpy(entry->name, attrName);

/* Link an existing previous element to this one */if (context->attrListPrevious)context->attrListPrevious->next = entry;

elseif ((context->attrListHead) == 0)context->attrListHead = entry;

/* Save the pointer to the previous element */context->attrListPrevious = entry;

}else {/* Error: Unable to allocate memory */

}

#ifdef _DEBUGif (context->tracefile) {fwprintf(context->tracefile, L”NODE: <%s> <- %s context=0x%x\n”,

context->nodeName, functionName, context);fflush(context->tracefile);

}#endif

return(entry);}

/******************************************************************************//* *//* Plugin Node Utility function: *//* *//* Return the terminal object for a named input terminal *//* *//******************************************************************************/void *getInputTerminalHandle(NODE_CONTEXT_ST* context,CciChar* terminalName

){static wchar_t* functionName=L”getInputTerminalHandle()”;TERMINAL_LIST_ENTRY *p = ((NODE_CONTEXT_ST *)context)->inputTerminalListHead;

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> -> %s context=0x%x terminalName : %s\n”,context->nodeName, functionName, context, terminalName);

fflush(context->tracefile);}

Appendix B. Source code for the SwitchNode plug-in 233

/* Scan the list for a matching terminal name */while (p != 0) {if (wcscmp(p->name, terminalName) == 0) {

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x matched\n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

/* Match found; return it */return(p->handle);

}p = p->next;

}

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x not matched\n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

/* No match was found */return(0);

}

/******************************************************************************//* *//* Plugin Node Utility function: *//* *//* Acquire storage for an input terminal entry and link it to the context *//* *//******************************************************************************/TERMINAL_LIST_ENTRY *insInputTerminalListEntry(NODE_CONTEXT_ST* context,CciChar* terminalName

){static wchar_t* functionName=L”insInputTerminalListEntry()”;TERMINAL_LIST_ENTRY* entry;int rc;

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> -> %s context=0x%x terminalName=’%s’\n”,context->nodeName, functionName, context, terminalName);

fflush(context->tracefile);}

entry = malloc(sizeof(TERMINAL_LIST_ENTRY));if (entry) {

/* This entry is the current end of the list */entry->next = 0;

/* Store the terminal name */wcscpy(entry->name, terminalName);

/* Create terminal and save its handle */entry->handle = cniCreateInputTerminal(&rc, context->nodeObject, terminalName);

234 Business Integration Solutions with MQSeries Integrator

/* Link an existing previous element to this one */if (context->inputTerminalListPrevious)context->inputTerminalListPrevious->next = entry;

elseif ((context->inputTerminalListHead) == 0)context->inputTerminalListHead = entry;

/* Save the pointer to the previous element */context->inputTerminalListPrevious = entry;

}else {/* Error: Unable to allocate memory */

}

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x\n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

return(entry);}

/******************************************************************************//* *//* Plugin Node Utility function: *//* *//* Return the terminal object for a named output terminal *//* *//******************************************************************************/void *getOutputTerminalHandle(NODE_CONTEXT_ST* context,CciChar* terminalName

){static wchar_t* functionName=L”getOutputTerminalHandle()”;TERMINAL_LIST_ENTRY *p = ((NODE_CONTEXT_ST *)context)->outputTerminalListHead;

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> -> %s context=0x%x terminalName : %s\n”,context->nodeName, functionName, context, terminalName);

fflush(context->tracefile);}

/* Scan the list for a matching terminal name */while (p != 0) {if (wcscmp(p->name, terminalName) == 0) {

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x matched\n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

/* Match found; return it */return(p->handle);

}p = p->next;

}

if (context->tracefile) {

Appendix B. Source code for the SwitchNode plug-in 235

fwprintf(context->tracefile,L”NODE: <%s> <- %s context=0x%x not matched\n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

/* No match was found */return(0);

}

/******************************************************************************//* *//* Plugin Node Utility function: *//* *//* Acquire storage for an output terminal and link it to the context *//* *//******************************************************************************/TERMINAL_LIST_ENTRY *insOutputTerminalListEntry(NODE_CONTEXT_ST* context,CciChar* terminalName

){static wchar_t* functionName=L”insOutputTerminalListEntry()”;TERMINAL_LIST_ENTRY* entry;int rc;

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> -> %s context=0x%x terminalName=’%s’\n”,context->nodeName, functionName, context, terminalName);

fflush(context->tracefile);}

entry = malloc(sizeof(TERMINAL_LIST_ENTRY));if (entry) {

/* This entry is the current end of the list */entry->next = 0;

/* Store the terminal name */wcscpy(entry->name, terminalName);

/* Create terminal and save its handle */entry->handle = cniCreateOutputTerminal(&rc, context->nodeObject, terminalName);

/* Link an existing previous element to this one */if (context->outputTerminalListPrevious)context->outputTerminalListPrevious->next = entry;

elseif ((context->outputTerminalListHead) == 0)context->outputTerminalListHead = entry;

/* Save the pointer to the previous element */context->outputTerminalListPrevious = entry;

}else {/* Error: Unable to allocate memory */

}

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x\n”,context->nodeName, functionName, context);

fflush(context->tracefile);

236 Business Integration Solutions with MQSeries Integrator

}

return(entry);}

void handleChangedTraceFile(NODE_CONTEXT_ST* context, CciChar* attrValue, int length){static wchar_t* functionName=L”handleChangedTraceFile()”;int i = 0, j = 0;

#ifdef _DEBUGif (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> -> %s context=0x%x attrValue=’%.*s’\n”,context->nodeName, functionName, context, length, attrValue);

fflush(context->tracefile);}

#endif

/* the trace is turned off for the moment, a change in the name of the trace file doesnot

trigger a new action */if (context->trace == 0) {

#ifdef _DEBUGif (context->tracefile) {fwprintf(context->tracefile, L”NODE: <%s> <- %s context=0x%x \n”,

context->nodeName, functionName, context);fflush(context->tracefile);

}#endifreturn;}

/* did we had a tracefile opened already ? */if (context->tracefile){

#ifdef _DEBUGfwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x closing current trace file\n”,context->nodeName, functionName, context);

#endiffclose(context->tracefile);

}

context->tracefile = _wfopen(attrValue, L”a+”);

#ifdef _DEBUGif (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x \n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

#endif

return;}

void handleChangedTraceSetting(NODE_CONTEXT_ST* context, int newValue, int oldValue){CciChar buffer[256];int i = 0, j = 0;

Appendix B. Source code for the SwitchNode plug-in 237

static wchar_t* functionName=L”handleChangedTraceSetting()”;

#ifdef _DEBUGif (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> -> %s context=0x%x\n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

#endif

context->trace = newValue;if (newValue == 0 && oldValue == 0){/* nothing to do */

#ifdef _DEBUGif (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x\n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

#endifreturn;}

if (newValue > 0 && oldValue > 0){/* nothing to do */

#ifdef _DEBUGif (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x\n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

#endifreturn;}

if (newValue == 0 && oldValue > 0){/* we might need to close the file */if (context->tracefile) {

#ifdef _DEBUGfwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x\n”,context->nodeName, functionName, context);

#endiffclose(context->tracefile);

}return;

}

if (newValue > 0 && oldValue == 0){/* we might need to open the file */memset(buffer, 0, sizeof(buffer));_getAttribute(context, L”nodeTraceOutfile”, buffer, sizeof(buffer));

context->tracefile = _wfopen(buffer, L”a+”);

#ifdef _DEBUG

238 Business Integration Solutions with MQSeries Integrator

if (context->tracefile) {fwprintf(context->tracefile,

L”NODE: <%s> <- %s context=0x%x\n”,context->nodeName, functionName, context);

fflush(context->tracefile);}

#endifreturn;

}

return;}

/******************************************************************************//* *//* Plugin Node Implementation Function: cniCreateNodeContext() *//* *//******************************************************************************/CciContext* _createNodeContext(CciFactory* factoryObject,CciChar* nodeName,CciNode* nodeObject

){static wchar_t* functionName=L”_createNodeContext()”;NODE_CONTEXT_ST* p;

/* Allocate a pointer to the local context */p = malloc(sizeof(NODE_CONTEXT_ST));

if (p) {

/* Clear the context area */memset(p, 0, sizeof(NODE_CONTEXT_ST));

/* Save our node object pointer in our context */p->nodeObject = nodeObject;

/* Save our node name */wcsncpy((wchar_t*)&p->nodeName, nodeName, MAX_NODE_NAME_LEN);

/* Initialise default trace setting */#ifdef _DEBUG

p->trace = 1;p->tracefile = fopen(“C:\\SwitchNode.trc”, “a+”);

#elsep->trace = 0;p->tracefile = NULL;

#endif

/* Create attributes and set default values */insAttrTblEntry(p, L”nodeTraceOutfile”, CNI_TYPE_STRING);insAttrTblEntry(p, L”nodeTraceSetting”, CNI_TYPE_INTEGER);

/* for the debug version of this modules, turn on early tracing */#ifdef _DEBUG

_setAttribute(p, L”nodeTraceOutfile”, L”C:\\SwitchNode.trc”);#else

_setAttribute(p, L”nodeTraceOutFile”, L””);#endif

#ifdef _DEBUG_setAttribute(p, L”nodeTraceSetting”, L”1”);

Appendix B. Source code for the SwitchNode plug-in 239

#else_setAttribute(p, L”nodeTraceSetting”, L”0”);

#endif

/* Create terminals */insInputTerminalListEntry(p, L”in”);insOutputTerminalListEntry(p, L”America”);insOutputTerminalListEntry(p, L”Danmark”);insOutputTerminalListEntry(p, L”United Kingdom”);insOutputTerminalListEntry(p, L”failure”);

/* Initialise default trace setting */#ifdef _DEBUG

p->trace = 1;#else

p->trace = 0;#endif

}else {/* Error: Unable to allocate memory */

}

displayEnvironment(p);

/* Return the pointer to the local context */return((CciContext*)p);

}

/******************************************************************************//* *//* Plugin Node Implementation Function: cniDeleteNodeContext() *//* *//* This function is called when an instance of a node is deleted. *//* *//******************************************************************************/void _deleteNodeContext(CciContext* context

){static wchar_t* functionName=L”_deleteNodeContext()”;NODE_CONTEXT_ST* p = context;

if (p->tracefile){fwprintf(p->tracefile, L”NODE: <%s> <- %s context=0x%x \n”,

p->nodeName, functionName, p);fclose(p->tracefile);

}

return;}

/******************************************************************************//* *//* Plugin Node Implementation Function: cniGetAttribute() *//* *//******************************************************************************/int _getAttributeName(CciContext* context,int index,CciChar* buffer,int bufsize

){

240 Business Integration Solutions with MQSeries Integrator

static wchar_t* functionName=L”_getAttributeName()”;int count = 0;ATTRIBUTE_TBL_ENTRY *p = ((NODE_CONTEXT_ST *)context)->attrListHead;NODE_CONTEXT_ST* q = context;

if (q->tracefile) {fwprintf(q->tracefile,

L”NODE: <%s> -> %s context=0x%x index=%ld\n”,q->nodeName, functionName, context, index);

fflush(q->tracefile);}

while (p != 0) {if (count == index) {wcscpy(buffer, p->name);

if (q->tracefile) {fwprintf(q->tracefile,

L”NODE: <%s> <- %s context=0x%x buffer=’%.*s’\n”,q->nodeName, functionName, context, bufsize, buffer);

fflush(q->tracefile);}

/* Normal return; attribute name returned */return(0);

}count++;p = p->next;

}

if (q->tracefile) {fwprintf(q->tracefile, L”NODE: <%s> <- %s context=0x%x not found\n”,

q->nodeName, functionName, context);fflush(q->tracefile);

}

/* Attribute not owned by the plugin node; defer to base */return(1);

}

/******************************************************************************//* *//* Plugin Node Implementation Function: cniSetAttribute() *//* *//******************************************************************************/int _setAttribute(CciContext* context,CciChar* attrName,CciChar* attrValue

){static wchar_t* functionName=L”_setAttribute()”;ATTRIBUTE_TBL_ENTRY* p = ((NODE_CONTEXT_ST *)context)->attrListHead;NODE_CONTEXT_ST* nc = context;int newValue, oldValue;

#ifdef _DEBUGif (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> -> %s context=0x%x attrName=’%s’ attrValue=’%s’\n”,nc->nodeName, functionName, context, attrName, attrValue);

fflush(nc->tracefile);}

#endif

Appendix B. Source code for the SwitchNode plug-in 241

while (p != 0) {if (wcscmp(p->name, attrName) == 0) {switch(p->type) {case CNI_TYPE_INTEGER:oldValue = *((int *)p->valptr);newValue = *((int *)p->valptr) = _wtoi(attrValue);break;

case CNI_TYPE_STRING:memcpy(p->valptr, attrValue, MAX_STRING_SIZE);

default:/* Error: Invalid datatype */break;

}

if (wcscmp(L”nodeTraceOutfile”,attrName) == 0) {handleChangedTraceFile(nc, attrValue, MAX_STRING_SIZE);

}if (wcscmp(L”nodeTraceSetting”, attrName) == 0) {handleChangedTraceSetting(nc, newValue, oldValue);

}

#ifdef _DEBUGif (nc->tracefile) {fwprintf(nc->tracefile, L”NODE: <%s> <- %s rc=0\n”,

nc->nodeName, functionName);fflush(nc->tracefile);

}#endif

/* Normal return; attribute value stored by plugin */return(0);}

p = p->next;}

#ifdef _DEBUGif (nc->trace) {fwprintf(nc->tracefile, L”NODE: <%s> <- %s rc=1\n”,

nc->nodeName, functionName);fflush(nc->tracefile);

}#endif

/* Attribute not owned by plugin */return(1);

}

/******************************************************************************//* *//* Plugin Node Implementation Function: cniGetAttribute() *//* *//******************************************************************************/int _getAttribute(CciContext* context,CciChar* attrName,CciChar* buffer,int bufsize

){static wchar_t* functionName=L”_getAttribute()”;ATTRIBUTE_TBL_ENTRY* p = ((NODE_CONTEXT_ST *)context)->attrListHead;NODE_CONTEXT_ST* nc = context;wchar_t wstring[256];

242 Business Integration Solutions with MQSeries Integrator

char string[256];

if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> -> %s context=0x%x attrName=’%s’\n”,nc->nodeName, functionName, context, attrName);

fflush(nc->tracefile);}

while (p != 0) {if (wcscmp(p->name, attrName) == 0) {switch(p->type) {case CNI_TYPE_INTEGER:sprintf((char*)&string, “%d”, *((int*)p->valptr));mbstowcs((wchar_t*)&wstring, (char*)&string, 256);wcsncpy(buffer, (wchar_t*)&wstring, min(bufsize, 256));break;

case CNI_TYPE_STRING:memcpy(buffer, p->valptr, min(MAX_STRING_SIZE, bufsize));

default:/* Error: Invalid datatype */break;

}

if (nc->tracefile) {fwprintf(nc->tracefile, L”NODE: <%s> <- %s rc=0\n”,

nc->nodeName, functionName);fflush(nc->tracefile);

}

/* Normal return; attribute value returned */return(0);

}p = p->next;

}

if (nc->tracefile) {fwprintf(nc->tracefile, L”NODE: <%s> <- %s rc=1\n”,

nc->nodeName, functionName);fflush(nc->tracefile);

}

/* Attribute not owned by plugin */return(1);

}

/******************************************************************************//* *//* Plugin Node Implementation Function: cniEvaluate() *//* *//******************************************************************************/void _evaluate(CciContext* context,CciMessage* destinationList,CciMessage* exceptionList,CciMessage* message

){static wchar_t* functionName=L”_evaluate()”;CCI_EXCEPTION_ST exception_st;NODE_CONTEXT_ST* nc = context;CciElement* bodyChild;CciElement* firstChild;CciElement* rootElement;

Appendix B. Source code for the SwitchNode plug-in 243

CciElement* element;CciTerminal* terminalObject;int bytes;int rc;int retvalue = 1;CciChar elementValue[256];CciChar elementName[256];

if (nc->tracefile) {fwprintf(nc->tracefile, L”NODE: <%s> -> %s context=0x%x \n”,

nc->nodeName, functionName, context);fflush(nc->tracefile);

}

/* Get the root element and it’s name */rootElement = cniRootElement(&rc, message);CCI_CHECK_RC();

/* Get the last child of root (ie the body) and it’s name */bodyChild = cniLastChild(&rc, rootElement);if (nc->tracefile) {

fwprintf(nc->tracefile,L”NODE: <%s> %s context=0x%x returncode cniLastChild : %ld\n”,nc->nodeName, functionName, context, rc);

fflush(nc->tracefile);}CCI_CHECK_RC();cniElementName(&rc, bodyChild, (CciChar*)&elementName, sizeof(elementName));if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x returncode cniElementName : %ld\n”,nc->nodeName, functionName, context, rc);

fflush(nc->tracefile);}CCI_CHECK_RC();if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x elementName : %s\n”,nc->nodeName, functionName, context, elementName);

fflush(nc->tracefile);}

/* Traverse to <Country> */

/* Navigate to the root of the XML message */firstChild = cniFirstChild(&rc, bodyChild);if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x returncode cniFirstChild : %ld\n”,nc->nodeName, functionName, context, rc);

fflush(nc->tracefile);}CCI_CHECK_RC();

element = findElementName(firstChild, L”Country”, nc);if (element == 0) {/* message has no element with the right name */terminalObject = getOutputTerminalHandle(context, L”failure”);if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x Country element not found\n”,nc->nodeName, functionName, context);

fwprintf(nc->tracefile,

244 Business Integration Solutions with MQSeries Integrator

L”NODE: <%s> %s context=0x%x terminal : %s\n”,nc->nodeName, functionName, context, L”failure”);

fflush(nc->tracefile);}

}

else {bytes = cniElementCharacterValue(&rc, element,

(CciChar*)&elementValue,sizeof(elementValue));

if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x returncode cniElementCharacterValue :%ld\n”,

nc->nodeName, functionName, context, rc);fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x elementValue : %.*s\n”,nc->nodeName, functionName, context, bytes, elementValue);

fflush(nc->tracefile);}

/* Decide which output terminal should receive the message, *//* based on the value */if (wcscmp(elementValue, L”America”) == 0)terminalObject = getOutputTerminalHandle(context, L”America”);

else if (wcscmp(elementValue, L”Danmark”) == 0)terminalObject = getOutputTerminalHandle(context, L”Danmark”);

else if (wcscmp(elementValue, L”United Kingdom”) == 0)terminalObject = getOutputTerminalHandle(context, L”United Kingdom”);

else {terminalObject = getOutputTerminalHandle(context, L”failure”);if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x Country element has illegal value\n”,nc->nodeName, functionName, context);

fwprintf(nc->tracefile,L”NODE: <%s> %s context=0x%x terminal : %s\n”,nc->nodeName, functionName, context, L”failure”);

fflush(nc->tracefile);}

}}

/* If the terminal exists and is attached, propagate to it */if (terminalObject) {if (cniIsTerminalAttached(&rc, terminalObject)) {if (rc == CCI_SUCCESS) {retvalue = cniPropagate(&rc, terminalObject,

destinationList, exceptionList, message);if (rc != CCI_SUCCESS) {if (rc == CCI_EXCEPTION) {/* Get details of the exception */cciGetLastExceptionData(&rc, &exception_st);

/* Any local error handling may go here */if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x exception : %s\n”,nc->nodeName, functionName, context, exception_st.traceText);

fflush(nc->tracefile);}

/* If the exception is “caught” it must be re-thrown */

Appendix B. Source code for the SwitchNode plug-in 245

cciRethrowLastException(0);}/* Some other error...log it */if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x propagate failed\n”,nc->nodeName, functionName, context);

fflush(nc->tracefile);}

}else {/* Message was propagated successfully */if (nc->tracefile) {fwprintf(nc->tracefile,

L”NODE: <%s> %s context=0x%x message propagated\n”,nc->nodeName, functionName, context);

fflush(nc->tracefile);}

}}else {if (rc == CCI_EXCEPTION) {cciRethrowLastException(0);

}else {/* Some other error...log it */cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, ““,

L”MQSeriesIntegrator2”, 0, “Error occurred”, 0);}

}}

}else {/* Terminal did not exist...severe internal error */cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, ““,

L”MQSeriesIntegrator2”, 0, “Terminal not connected”, 0);}

if (nc->tracefile) {fwprintf(nc->tracefile, L”NODE: <%s> <- %s context=0x%x\n\n”,

nc->nodeName, functionName, context);fflush(nc->tracefile);

}return;

}

/******************************************************************************//* *//* Plugin Node Utility function: *//* *//* Node definition - ComIbmSampleSwitchNode *//* *//******************************************************************************/void defineSwitchNode(void* factoryObject

){static wchar_t* functionName=L”defineSwitchNode()”;static CNI_VFT vftable;

/* Setup function table with pointers to node implementation functions */memset(&vftable, 0, sizeof(vftable));vftable.iFpCreateNodeContext = _createNodeContext;vftable.iFpDeleteNodeContext = _deleteNodeContext;

246 Business Integration Solutions with MQSeries Integrator

vftable.iFpGetAttributeName = _getAttributeName;vftable.iFpSetAttribute = _setAttribute;vftable.iFpGetAttribute = _getAttribute;vftable.iFpEvaluate = _evaluate;

/* Define a node type supported by our factory. If any errors/exceptions *//* occur during the execution of this utility function, then as we have not *//* supplied the returnCode argument, the exception will bypass the plugin *//* and be directly handled by the broker. */cniDefineNodeClass(0, factoryObject, L”SwitchNode”, &vftable);

return;}

/******************************************************************************//* *//* Plugin Node Implementation Function: *//* *//* This function is called when the message broker loads the “lil” during the *//* initialization of the broker engine. *//* *//* The responsibilities of the plug-in are to: *//* - create the node factory (or factories) which the “lil” supports, using *//* the createNodeFactory() function, saving the returned pointer to the *//* node factory for use at runtime. *//* - define each node supported by the (or each) factory) and pass a pointer *//* to a function table which contains pointers to the node implementation *//* functions. *//* - define the name of each attribute supported by each node, including a *//* pointer to a validation function. *//* - define input and output terminals supported by each node. *//* - return the pointer to the factory, unless an error occurred, in which *//* case zero should be returned. *//* *//******************************************************************************/CciFactory LilFactoryExportPrefix * LilFactoryExportSuffixbipGetMessageflowNodeFactory(){static wchar_t* functionName=L”bipGetMessageflowNodeFactory()”;CciFactory* factoryObject;int rc = 0;CciChar factoryName[] = L”SwitchNodeFactory”;CCI_EXCEPTION_ST exception_st;

/* Create the Node Factory for this plug-in */factoryObject = cniCreateNodeFactory(0, factoryName);if (factoryObject == CCI_NULL_ADDR) {if (rc == CCI_EXCEPTION) {/* Get details of the exception */cciGetLastExceptionData(&rc, &exception_st);

/* Any local error handling may go here */

/* Rethrow the exception */cciRethrowLastException(&rc);

}/* Any further local error handling can go here */

}else {/* Define the nodes supported by this factory */defineSwitchNode(factoryObject);

}

Appendix B. Source code for the SwitchNode plug-in 247

/* Return address of this factory object to the broker */return(factoryObject);

}

248 Business Integration Solutions with MQSeries Integrator

Appendix C. Using the additional material

Some additional material has been made available. It includes the sourcecode for the SwitchNode plug-in and the source code for the components ofthe Single Customer View application.

C.1 Locating the additional material on the Internet

The Web material associated with this redbook is available in softcopy on theInternet from the IBM Redbooks Web server. Point your Web browser to:

ftp://www.redbooks.ibm.com/redbooks/SG246154

Alternatively, you can go to the IBM Redbooks Web site at:

http://www.redbooks.ibm.com/

Select Additional materials and open the directory that corresponds with theredbook form number.

C.2 Using the Web material

The additional Web material that accompanies this redbook includes thefollowing:

File name DescriptionSwitchNode.zip Sources for the SwitchNodeSCV.zip Sources for the single customer view application

C.2.1 System requirements for downloading the Web material

The following system configuration is recommended for using the additionalWeb material.

Operating System: Windows NT Version 4Processor: Pentium IIMemory: 256 MB

C.2.2 How to use the Web material

Create a subdirectory (folder) on your workstation and copy the contents ofthe Web material into this folder.

© Copyright IBM Corp. 2000 249

C.2.3 Material for the single customer view application

The file SVC.zip contains the following files.

C.2.3.1 Back-end application getpolicytd.cThis program simulates an MQSeries-enabled legacy back-end application.The name of the inbound queue that it monitors is passed to it when theprogram is started. It writes its response messages to the reply-to queuenamed on the request message. The simulated responses are stored in textfiles.

C.2.3.2 ClientServlet Java filesThe servlet is built up by the following Java class files:

• CustomerDetailsCommand.java

• CustomerDetailsServlet.java

• EndowBckndRepMsg.java

• endowPolicy.java

• GeneralMQException.java

• HouseBckndRepMsg.java

• housePolicy.java

• InvalidParameterException.java

• MotorBckndRepMsg.java

• motorPolicy.java

• NewRecord.java

• Policy.java

• TableView.java

C.2.3.3 MsgMerger Java applicationThe MsgMerger is built up by two Java class files:

• MessageMerger.java

• MergerThread.java

The MessageMerger class monitors the MERGER.TRIGGER.QUEUE andspawns a copy of MergerThread for each trigger message it receives.

The MergerThread class monitors MQSI.REPLY.QUEUE for responsemessages from the legacy back-end applications. It waits for the expectednumber of response messages before merging these messages into a single

250 Business Integration Solutions with MQSeries Integrator

message and writing them to the reply-to queue name from the triggermessage.

C.2.3.4 WebSphere filesThe following files are used to build the Web pages:

• clearpixel.gif

• Header.html

• index.html

• main.html

• results.html

• resultsjsp.jsp

• SCView_NCorpBanner.gif

C.2.3.5 Data files• endowout.txt

• houseout.txt

• motorout.txt

These are the data files used by getpolicytd to simulate a response messagefrom the legacy back-end applications.

C.2.3.6 Command files• MQIServsTD.cmd

This is the command file used to start three copies of getpolicytd to simulatethe three legacy back-end applications: Endow, House, and Motor.

• StartJavaApps.cmd

This is the command file used to start the Message Merger Java application.

• StartWebBrowser.cmd

This is the command file used to start the Web browser and display the singlecustomer view Web page.

• compileMM.cmd

This command file compiles the Message Merger Java applets and copiesthem to the appropriate directories for execution.

• compileServlet.cmd

Appendix C. Using the additional material 251

This command file compiles the ClientServlet Java applets and copies themto the appropriate directories for execution.

• PublishHTML.cmd

This command file copies the HTML files from the installation directories tothe execution directories.

252 Business Integration Solutions with MQSeries Integrator

Appendix D. Special notices

This publication is intended to help application architects and designers tobuild business integration solutions based on MQSeries Integrator Theinformation in this publication is not intended as the specification of anyprogramming interfaces that are provided by MQSeries Integrator. See thePUBLICATIONS section of the IBM Programming Announcement forMQSeries Integrator for more information about what publications areconsidered to be product documentation.

References in this publication to IBM products, programs or services do notimply that IBM intends to make these available in all countries in which IBMoperates. Any reference to an IBM product, program, or service is notintended to state or imply that only IBM's product, program, or service may beused. Any functionally equivalent program that does not infringe any of IBM'sintellectual property rights may be used instead of the IBM product, programor service.

Information in this book was developed in conjunction with use of theequipment specified, and is limited in application to those specific hardwareand software products and levels.

IBM may have patents or pending patent applications covering subject matterin this document. The furnishing of this document does not give you anylicense to these patents. You can send license inquiries, in writing, to the IBMDirector of Licensing, IBM Corporation, North Castle Drive, Armonk, NY10504-1785.

Licensees of this program who wish to have information about it for thepurpose of enabling: (i) the exchange of information between independentlycreated programs and other programs (including this one) and (ii) the mutualuse of the information which has been exchanged, should contact IBMCorporation, Dept. 600A, Mail Drop 1329, Somers, NY 10589 USA.

Such information may be available, subject to appropriate terms andconditions, including in some cases, payment of a fee.

The information contained in this document has not been submitted to anyformal IBM test and is distributed AS IS. The use of this information or theimplementation of any of these techniques is a customer responsibility anddepends on the customer's ability to evaluate and integrate them into thecustomer's operational environment. While each item may have beenreviewed by IBM for accuracy in a specific situation, there is no guaranteethat the same or similar results will be obtained elsewhere. Customers

© Copyright IBM Corp. 2000 253

attempting to adapt these techniques to their own environments do so at theirown risk.

Any pointers in this publication to external Web sites are provided forconvenience only and do not in any manner serve as an endorsement ofthese Web sites.

The following terms are trademarks of the International Business MachinesCorporation in the United States and/or other countries:

The following terms are trademarks of other companies:

Tivoli, Manage. Anything. Anywhere.,The Power To Manage., Anything.Anywhere.,TME, NetView, Cross-Site, Tivoli Ready, Tivoli Certified, PlanetTivoli, and Tivoli Enterprise are trademarks or registered trademarks of TivoliSystems Inc., an IBM company, in the United States, other countries, or both.In Denmark, Tivoli is a trademark licensed from Kjøbenhavns Sommer - TivoliA/S.

C-bus is a trademark of Corollary, Inc. in the United States and/or othercountries.

Java and all Java-based trademarks and logos are trademarks or registeredtrademarks of Sun Microsystems, Inc. in the United States and/or othercountries.

Microsoft, Windows, Windows NT, and the Windows logo are trademarks ofMicrosoft Corporation in the United States and/or other countries.

PC Direct is a trademark of Ziff Communications Company in the UnitedStates and/or other countries and is used by IBM Corporation under license.

ActionMedia, LANDesk, MMX, Pentium and ProShare are trademarks of IntelCorporation in the United States and/or other countries.

AIX AS/400CICS CS SystemsDB2 DB2 Universal DatabaseIBM MQSeriesNetfinity OS/390RS/6000 S/390ServicePac SPSupportPac System/390ThinkPad WebSphere

254 Business Integration Solutions with MQSeries Integrator

UNIX is a registered trademark in the United States and other countrieslicensed exclusively through The Open Group.

SET, SET Secure Electronic Transaction, and the SET Logo are trademarksowned by SET Secure Electronic Transaction LLC.

Other company, product, and service names may be trademarks or servicemarks of others.

Appendix D. Special notices 255

256 Business Integration Solutions with MQSeries Integrator

Appendix E. Related publications

The publications listed in this section are considered particularly suitable for amore detailed discussion of the topics covered in this redbook.

E.1 IBM Redbooks

For information on ordering these publications see “How to get IBMRedbooks” on page 259.

• MQSeries Version 5.1 Administration and Programming Examples,SG24-5849

• Using the MQSeries Integrator Version 1.0, SG24-5386

• WebSphere Application Servers: Standard and Advanced Editions,SG24-5460

• Patterns for e-business: User-to-Business Patterns for Topology 1 and 2using WebSphere Advanced Edition, SG24-5864

E.2 IBM Redbooks collections

Redbooks are also available on the following CD-ROMs. Click the CD-ROMsbutton at http://www.redbooks.ibm.com/ for information about all the CD-ROMsoffered, updates and formats.

E.3 Referenced Web sites

These Web sites are also relevant as further information sources:

• http://www-4.ibm.com/software/ts/mqseries/ MQSeries Family homepage

CD-ROM Title Collection KitNumber

IBM System/390 Redbooks Collection SK2T-2177IBM Networking Redbooks Collection SK2T-6022IBM Transaction Processing and Data Management Redbooks Collection SK2T-8038IBM Lotus Redbooks Collection SK2T-8039Tivoli Redbooks Collection SK2T-8044IBM AS/400 Redbooks Collection SK2T-2849IBM Netfinity Hardware and Software Redbooks Collection SK2T-8046IBM RS/6000 Redbooks Collection SK2T-8043IBM Application Development Redbooks Collection SK2T-8037IBM Enterprise Storage and Systems Management Solutions SK3T-3694

© Copyright IBM Corp. 2000 257

• http://www-4.ibm.com/software/ts/mqseries/integrator/ MQSeriesIntegrator home page

• http://www-4.ibm.com/software/ts/mqseries/workflow/ MQSeriesWorkflow home page

• http://www-4.ibm.com/software/ts/mqseries/txppacs/txpsumm.html/

MQSeries SupportPacs library

• http://www-4.ibm.com/software/developer/web/patterns/ Patterns fore-business

• http://www-3.ibm.com/services/learning/roadmaps/adxml01.htm XMLEducation

258 Business Integration Solutions with MQSeries Integrator

How to get IBM Redbooks

This section explains how both customers and IBM employees can find out about IBM Redbooks,redpieces, and CD-ROMs. A form for ordering books and CD-ROMs by fax or e-mail is also provided.

• Redbooks Web Site ibm.com/redbooks

Search for, view, download, or order hardcopy/CD-ROM Redbooks from the Redbooks Web site.Also read redpieces and download additional materials (code samples or diskette/CD-ROM images)from this Redbooks site.

Redpieces are Redbooks in progress; not all Redbooks become redpieces and sometimes just a fewchapters will be published this way. The intent is to get the information out much quicker than theformal publishing process allows.

• E-mail Orders

Send orders by e-mail including information from the IBM Redbooks fax order form to:

• Telephone Orders

• Fax Orders

This information was current at the time of publication, but is continually subject to change. The latestinformation may be found at the Redbooks Web site.

In United States or CanadaOutside North America

e-mail [email protected] information is in the “How to Order” section at this site:http://www.elink.ibmlink.ibm.com/pbl/pbl

United States (toll free)Canada (toll free)Outside North America

1-800-879-27551-800-IBM-4YOUCountry coordinator phone number is in the “How to Order”section at this site:http://www.elink.ibmlink.ibm.com/pbl/pbl

United States (toll free)CanadaOutside North America

1-800-445-92691-403-267-4455Fax phone number is in the “How to Order” section at this site:http://www.elink.ibmlink.ibm.com/pbl/pbl

IBM employees may register for information on workshops, residencies, and Redbooks by accessingthe IBM Intranet Web site at http://w3.itso.ibm.com/ and clicking the ITSO Mailing List button.Look in the Materials repository for workshops, presentations, papers, and Web pages developedand written by the ITSO technical professionals; click the Additional Materials button. Employees mayaccess MyNews at http://w3.ibm.com/ for redbook, residency, and workshop announcements.

IBM Intranet for Employees

© Copyright IBM Corp. 2000 259

IBM Redbooks fax order form

Please send me the following:

We accept American Express, Diners, Eurocard, Master Card, and Visa. Payment by credit card notavailable in all countries. Signature mandatory for credit card payment.

Title Order Number Quantity

First name Last name

Company

Address

City Postal code

Telephone number Telefax number VAT number

Invoice to customer number

Country

Credit card number

Credit card expiration date SignatureCard issued to

260 Business Integration Solutions with MQSeries Integrator

Glossary

application messaging interface (AMI). Theprogramming interface provided by MQSeriesthat defines a high level interface to messagequeuing services. See also MQI and JMS.

broker. See message broker.

broker domain A set of brokers that share asingle Configuration Manager.

cluster. A network of queue managers that arelogically related.

cluster queue. A queue that is hosted by acluster queue manager and made available toother queue managers in the cluster.

Cluster Queue Manager. A queue managerthat is member of a cluster. A queue managercan be member of more than one cluster.

cluster-receiver channel. A channel on whichcluster queue managers can receive messagesfrom other queue managers in the cluster andcluster information from the repository queuemanagers.

cluster-sender channel. A channel on whicha cluster queue manager can send messages toother queue managers in the cluster and clusterinformation to the repository queue manager.

collective. A set of interconnected brokersforming part of a multi-broker network forpublish/subscribe applications.

Configuration Manager. A component ofMQSeries Integrator that acts as the interfacebetween the configuration repository and anexecuting set of brokers.

Configuration Repository. Persistent storagefor broker and topology configuration.

Control Center. The graphical interface thatprovides facilities for defining, configuring,deploying and monitoring MQSeries Integratorresources.

deploy. The step to make a resourceoperational.

© Copyright IBM Corp. 2000

e-business. Electronic business, a term usedto describe the commercial use of the Internetand the World Wide Web.

execution group. A named grouping ofmessage flows that have been assigned to abroker.

full repository. A complete set of informationabout every queue manager in the cluster.

Java Database Connectivity (JDBC). Anapplication programming interface that has thesame characteristics as ODBC but is specificallydesigned for use by Java database applications.

Java Development Kit (JDK). A softwarepackage that can be used to write, compile,debug, and run Java applets and applications.

Java Message Service (JMS). An applicationprogramming interface that provides Javalanguage functions for message handling.

Java Runtime Environment (JRE). A subsetof the Java Development Kit that contains thecore executables and files that constitute theJava platform. The JRE includes the JavaVirtual Machine.

message broker. A set of executingprocesses hosting one or more message flows.

message dictionary. A repository formessage type specifications.

message domain. The source of a messagedefinition.

message flow. A directed graph thatrepresents a set of activities performed on amessage or event as it passes through a broker.A message flow consists of a number ofmessage processing nodes.

message parser. Component that interpretsthe bitstream of a message.

message processing node. A step in themessage flow representing a well-definedactivity. A node can be one of the primitivenodes or a representation of a subflow.

261

Message Queue Interface (MQI). Theapplication programming interface provided byMQSeries queue managers. See also JMS andAMI.

MQRFH. An architected message header that isused to provide metadata for the processing of amessage.

MQRFH2. An extended version of MQRFH toprovide extra function in the message processing.

Open Database Connectivity (ODBC). Astandard application programming interface (API)for accessing data in both relational andnon-relational database management systems.Using this API, database applications can accessdata stored in database management systems ona variety of computers even if each databasemanagement system uses a different datastorage format and programming interface.ODBC is based on the call level interface (CLI)specification of the X/Open SQL Access Group.

plug-in. an extension of the product to provideadditional message processing nodes and/ormessage parsers.

point-to-point. Application design pattern formessaging applications where the sender of themessage has knowledge about the receiver of themessage. Compare with publish/subscribe.

publish/subscribe. Application design patternfor messaging applications where the producer ofthe message (publisher) is decoupled from theconsumer of the message (subscriber). Thedelivery of the message is under the control ofthe broker. Subscriptions can be topic based orcontent based.

queue. An MQSeries object. Applications canput messages on, and get messages from, aqueue. A queue is owned and managed by aqueue manager. A local queue is a type of queuethat can contain a list of messages waiting to beprocessed. Other types of queues cannot containmessages but are used to point to other queues.

queue manager. A subsystem that providesqueuing services to applications. It provides anapplication programming interface (the MQI) so

that programs can access messages on thequeues that are owned by the queue manager.

User Name Server. A MQSeries Integratorcomponent that interfaces with operating systemfacilities to determine valid users and groups.

XML. Extensible Markup Language, a standardfor the representation of data.

262 Business Integration Solutions with MQSeries Integrator

Abbreviations and acronyms

ACL access control list

AIX Advanced InteractiveeXecutive

AMI application messaginginterface

API applicationprogramming interface

BLOB binary large object

CICS customer informationcontrol center

CMI common messaginginterface

CSD corrective servicediskette

CWF Custom Wire Format

DB2 Database 2

DLL dynamic link library

DOS disk operating system

DTD document typedefinition

ESQL enhanced structuredquery language

GIF graphics interchangeformat

GUI graphical user interface

HTML HyperText MarkupLanguage

HTTP HyperText TransferProtocol

IBM International BusinessMachines Corporation

IMS InformationManagement System

ITSO International TechnicalSupport Organization

© Copyright IBM Corp. 2000

JDBC Java DatabaseConnectivity

JDK Java Development Kit

JMS Java Message Service

JRE Java RuntimeEnvironment

lil loadableimplementation library

LU logical unit

MQI Message QueueInterface

MRM Message RepositoryManager

NetBIOS network basic inputoutput system

ODBC Open DatabaseConnectivity

OS/390 Operating System forS/390

PCF programmablecommand format

PDF portable documentformat

SAP Systems, Applications,Products in DataProcessing

SGML standard generalizedmarkup language

SNA Systems NetworkArchitecture

SPX Sequenced PacketExchange

SQL structured querylanguage

TCP/IP Transmission ControlProtocol/InternetProtocol

263

XML Extensible MarkupLanguage

264 Business Integration Solutions with MQSeries Integrator

Index

Aadministrative agent 13API

implementation functions 138utility functions 138

BBLOB

message domain 19

CC COBOL Importer 104cluster receiver 77cluster sender 77common message interface 4Compute node 5, 54Configuration Manager 6

creating 36dependencies 17starting 45

configuration repository 6Control Center 7

adding a plug-in 141set-up 44

Custom Wire FormatSee CWF

CWF 19, 102

DDatabase node 5Databases

creation 30dependencies 18ODBC configuration 30

DB2 Enterprise Edition 21Document Type Definitions 69DTD 19, 69

EESQL 5, 123Event Viewer 46, 89execution group 60, 96

© Copyright IBM Corp. 2000

FFilter node 5, 117full repository queue manager 76

Ggeneric XML messages 18

HHTML 68HTTP 68

IIBMPrimitives 6

Llil 14, 137loadable implementation library

See lil

Mmessage broker 10

Adding an execution group 96creating 39dependencies 17instance name 12registering 51starting 45

message domain 19message flow 4

assignment to a broker 60creating 53deploying 62

message flow execution engine 14message format 19message repository 6message set 19, 102message type 19MQInput node 5, 54MQOutput node 5, 54MQRFH 20MQRFH2 20MQSeries Clustering 74MQSeries Explorer 64, 79MRM

message domain 19

265

multi-broker domain 92

NNEON

message domain 19

OODBC Configuration 30

Pparser 137plug-in 137predefined messages 18

Rrunmqsc 64, 84

Sself-defined messages 18SGML 68SQL 123

UUser Name Server 14

creating 42dependencies 18starting 45

user-written node 137

WWarehouse node 5well-formed XML 69Windows NT service tasks 44wire format

See CWFworkspace 53

XXML 18, 68

message domain 19refering to a DTD 69, 70sample document 67sample message 99

266 Business Integration Solutions with MQSeries Integrator

© Copyright IBM Corp. 2000 267

IBM Redbooks review

Your feedback is valued by the Redbook authors. In particular we are interested in situations where aRedbook "made the difference" in a task or problem you encountered. Using one of the followingmethods, please review the Redbook, addressing value, subject matter, structure, depth andquality as appropriate.

• Use the online Contact us review redbook form found at ibm.com/redbooks• Fax this form to: USA International Access Code + 1 914 432 8264• Send your comments in an Internet note to [email protected]

Document NumberRedbook Title

SG24-6154-00Business Integration Solutions with MQSeries Integrator

Review

What other subjects would youlike to see IBM Redbooksaddress?

Please rate your overallsatisfaction:

O Very Good O Good O Average O Poor

Please identify yourself asbelonging to one of thefollowing groups:

O Customer O Business Partner O Solution DeveloperO IBM, Lotus or Tivoli EmployeeO None of the above

Your email address:The data you provide here maybe used to provide you withinformation from IBM or ourbusiness partners about ourproducts, services or activities.

O Please do not use the information collected here for futuremarketing or promotional contacts or other communications beyondthe scope of this transaction.

Questions about IBM’s privacypolicy?

The following link explains how we protect your personal information.ibm.com/privacy/yourprivacy/

(0.5” spine)0.475”<->0.875”

250 <-> 459 pages

Business Integration Solutions with M

QSeries Integrator

®

SG24-6154-00 ISBN 0738417254

INTERNATIONAL TECHNICALSUPPORTORGANIZATION

BUILDING TECHNICALINFORMATION BASED ONPRACTICAL EXPERIENCE

IBM Redbooks are developed by the IBM International Technical Support Organization. Experts from IBM, Customers and Partners from around the world create timely technical information based on realistic scenarios. Specific recommendations are provided to help you implement IT solutions more effectively in your environment.

For more information:ibm.com/redbooks

Business Integration Solutions withMQSeries Integrator

Exploring the latest version of MQSeries Integrator

Extending the functionality of MQSeries Integrator

Providing a single customer view solution

Very often information about a customer is stored in product-centric databases. You can imagine an insurance company that has one database for each type of insurance they sell. However, when customers want to obtain information about their current insurance contracts, they want to see a single view of that information, and not submit a query for each contract they might have. This IBM Redbook outlines the messaging techniques that one can implement to obtain a user-friendly single customer view, using MQSeries Integrator.

This redbook explores the functionality of the latest version of MQSeries Integrator and provides guidance on installation and configuration. A number of message flows are developed. These message flows are the implementation of business rules that need to be executed by the MQSeries Integrator broker. The redbook also explains how to extend the functionality of MQSeries Integrator with user-written plug-in nodes.

The book also describes a Web-enabled single customer view solution. This solution uses WebSphere, DB2, MQSeries, and MQSeries Integrator to solve a common business integration problem: how to get a single view of all the information about one customer?