Skip to main content

Extending WebSphere MQ Integrator Broker V2.1 and WebSphere Business Integration Message Broker V5

ESQL functionality with plug-in parsers

Martin Smolny (Martin.Smolny@de.ibm.com), Software engineer, IBM
Martin Smolny works on the WebSphere Business Process Choreographer team in Boeblingen, Germany. He has worked on different IBM products and has seven years of experience in business integration software. Martin completed his studies of Information Technology in Stuttgart.

Summary:  This article describes a new way to extend the functionality of WebSphere® Business Integration Message Broker V5 and WebSphere MQ Integrator Broker V2.1 by using Extended SQL (ESQL). It uses a simplified case study, with extensive sample code, to implement a plug-in parser and add trace calls to the ESQL code.

Date:  21 Jul 2004
Level:  Intermediate
Activity:  313 views

ESQL -- A short overview

WebSphere MQ Integrator Broker V2.1 and WebSphere Business Integration Message Broker V5 offer Extended SQL (ESQL), a powerful language for message and database content manipulation. This language is derived from SQL Version 3. Unlike SQL, an ESQL program may consist of a number of statements that are executed in their written order. Language elements like IF-conditions and WHILE-loops are also supported and allow the implementation of complex processing. Message manipulation is easy and the implemented code is portable across all supported platforms.

With the new version WebSphere Business Integration Message Broker V5, ESQL offers new language elements that allow the implementation of common functionality in so-called procedures and functions. Though this is a major enhancement, merely procedures or functions in ESQL -- and no other language -- can be implemented.

This article refers to WebSphere MQ Integrator Broker V2.1 since it was developed using WebSphere MQ Integrator Broker, but the information in this article also applies to WebSphere MQ Integration Message Broker V5.


Extending WebSphere MQ Integrator Broker

To extend the functionality of WebSphere MQ Integrator Broker outside the limits of ESQL, plug-in nodes in C or Java™ can be implemented. Plug-in nodes constitute a powerful way to implement interesting functionality, but there are situations in which this approach leads to very complex processing:

Imagine a company with a server-based user directory that can be used to check e-mail addresses on their validity. A programmer has to implement a flow that processes the message in Listing 1 and check all recipients' e-mail addresses on their existence in this directory.


Listing 1. Sample message to process
<CompanyNewsletter>
  <Recipients>
    <Recipient>john@doe.com</Recipient>
    <Recipient>jane@doe.com</Recipient>
    ...
  </Recipients>
  <Text>
    ...
  </Text>
</CompanyNewsletter>

The company has a plug-in node that is capable of checking one e-mail address against this directory. If this component is used, the only way to implement the processing is to use a compute node. This contains a loop in ESQL which builds a request message for each e-mail address and propagates this request message to the plug-in node (see Listing 2). If no exception occurs, that is, the processing of the plug-in node was successful, the ESQL code proceeds.


Listing 2. Solution with ESQL and a plug-in node
WHILE condition
  build request message to check for e-Mail-address
  PROPAGATE
END WHILE;
send newsletter

If there was the -- more comfortable -- possibility to check the e-mail address within the ESQL loop, there would be no need to build a message structure for each recipient. Building such a message will cost some coding effort and is slow in its execution.

The following case study shows an elegant way to implement functionality in C that can be accessed using ESQL. As the main focus of this article lies on the implementation of a plug-in parser, a simplified case study is used to demonstrate it.


Case study

For professional software developers, it is common to use trace functionality in a product running in a customer's environment. For ESQL programs, WebSphere MQ Integrator Broker offers to set the User Trace to the level, debug. This produces a very detailed trace for all code execution that took place in ESQL. The level, normal, shows no ESQL execution trace at all. This case study implements a trace functionality that also works with the level, normal. The implementation lets the programmer control the trace granularity according to his needs.

To demonstrate the usage of tracing, Figure 1 shows a simple flow that takes an input message, extracts the elements, Net and Tax, and calculates the element, Gross. The result is set into the message and propagated to the output queue.


Figure 1. Flow with ESQL code
Screenshot of flow with ESQL code

SET OutputRoot = InputRoot;
-- Enter SQL below this line. SQL above this line might be
   regenerated, causing any  modifications to be lost.

DECLARE pRefNet REFERENCE TO OutputRoot.XML.Bill.Net;
DECLARE pRefTax REFERENCE TO OutputRoot.XML.Bill.Tax;
DECLARE pRefGross REFERENCE TO OutputRoot.XML.Bill.Gross;

SET pRefGross = CAST(pRefNet AS DECIMAL) * 
                CAST(pRefTax AS DECIMAL) +
                CAST(pRetNet AS DECIMAL);


The aim of this case study is to add some trace calls to the ESQL code of Figure 1. These trace calls should be written to the WebSphere MQ Integrator Broker User Trace using the provided C function cciLog(). To achieve this, a plug-in parser has to be implemented.


Plug-in parser CciLogParser

WebSphere MQ Integrator Broker provides an API to implement plug-in parsers. These parsers are intended to read message representations that cannot be accessed with the already built-in parsers of WebSphere MQ Integrator Broker and convert them to a logical message tree. If you are interested in further information on plug-in parsers beyond the scope of this article, you can refer to the WebSphere MQ Integrator Broker User Programming Guide.

The CciLogParser is implemented in C and not in Java, as Java can be used to implement plug-in nodes, but is not supported for the implementation of plug-in parsers. Every plug-in parser must provide a function named bipGetParserFactory() (see Listing 3). This function defines the parser factory ComIbmSampleCciLogParserFactory and a parser class CCILOG. Both names must be unique in one broker's environment.


Listing 3. Implementation of bipGetParserFactory()

void LilFactoryExportPrefix * LilFactoryExportSuffix bipGetParserFactory(void) {
  CciFactory*     factoryObject;
  int             rc;
  static CPI_VFT  vftable = {CPI_VFT_DEFAULT};

  // initialize the constants used by this plug-in
  initParserConstants();

  // setup function table with pointers to parser implementation functions
  vftable.iFpParseBufferEncoded       = cpiParseAndWriteBufferEncoded;
  vftable.iFpWriteBufferEncoded       = cpiParseAndWriteBufferEncoded;
  vftable.iFpSetElementValue          = cpiSetElementValue;
  vftable.iFpElementValue             = cpiElementValue;

  // mandatory functions, otherwise WMQI does not use this parser
  vftable.iFpCreateContext            = cpiCreateContext;
  vftable.iFpParseFirstChild          = cpiParseFirstLastChildAndPreviousNextSibling;
  vftable.iFpParseLastChild           = cpiParseFirstLastChildAndPreviousNextSibling;
  vftable.iFpParsePreviousSibling     = cpiParseFirstLastChildAndPreviousNextSibling;
  vftable.iFpParseNextSibling         = cpiParseFirstLastChildAndPreviousNextSibling;

  // create the parser factory for this plugin
  factoryObject = cpiCreateParserFactory(&rc, constParserFactory);
  if (factoryObject) {
    // Define the classes of message supported by the factory
    cpiDefineParserClass(&rc, factoryObject, constParserClass, &vftable);
  } else {
      static char* errMsg = "CciLogParser.lil: error creating" 
                            " the parser factory " CONST_PARSER_FACTORY;
      cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "bipGetParserFactory()",  
             constWBIMBCatalog, 3001, errMsg, errMsg, CONST_VIRTUALTRACENODENAME, 0);
  }

  return(factoryObject);
}


Most of this plug-in parser's implementation functions consist of a simple return statement. To get access to values passed by ESQL, this parser implements cpiSetElementValue() and its counterpart cpiElementValue(), which is necessary to enable the return of values to WebSphere MQ Integrator Broker. Using the sample plug-in parser shipped with WebSphere MQ Integrator Broker V2.1, the implementation of these two functions is straight forward:


Listing 4. Implementation of cpiSetElementValue()
// -----------------------------------------------------------------------------
// Plugin Parser Implementation Function
void cpiSetElementValue(CciParser* parser, CciElement* element, CciElementValue* value) {

  CciElement* valueElement;
  CciSize     bufferSize;
  int         rc;
  CciChar     buffer[1024]; // maximum supported length of message
  char        charBuffer[1024];

  // set the value
  valueElement = element;
  if ((cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_VALUE) ||
      (cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_NAME_VALUE))  {
    cpiSetElementValueValue(&rc, element, value);
  } else if (cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_NAME) {
    /* Create a new value element, add as a first child, and set the value */
    valueElement = cpiCreateElement(&rc, parser);
    cpiSetElementType(&rc, valueElement, CCI_ELEMENT_TYPE_VALUE);
    cpiSetElementValueValue(&rc, valueElement, value);
    cpiAddAsFirstChild(&rc, element, valueElement);
  }

  buffer[0] = 0;
  bufferSize = cpiElementCharacterValue(&rc, valueElement, buffer, 1023);

  if (rc==CCI_EXCEPTION) {
    cciRethrowLastException(&rc);
  } else if (rc==CCI_SUCCESS) {
    cciUcsToMbs(&rc, buffer, charBuffer, 1023, BIP_DEF_COMP_CCSID);
    if (rc!=CCI_SUCCESS) {
      // Error occured, e.g the message contained non-ASCII 
      // characters which were expanded to more than one byte per character.
      sprintf(charBuffer, "CciLogParser.lil: error converting the log text "
                          "into a C-string, error code %i", rc);
      cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "cpiSetElementValue()", 
             constWBIMBCatalog, 3001, charBuffer, 
             charBuffer, CONST_VIRTUALTRACENODENAME, 0);             
    } else {
      // the original intend of this parser; write the message to the WMQI log
      cciLog(&rc, CCI_LOG_INFORMATION, __FILE__, __LINE__, "cpiSetElementValue()",
             constWBIMBCatalog, 3001, charBuffer, 
             charBuffer, CONST_VIRTUALTRACENODENAME, 0);
    }
  } else if (rc==CCI_BUFFER_TOO_SMALL) {
    // here we could allocate a new buffer and retrieve the text again,
    // but this sample just writes an error to the log
    strcpy(charBuffer, "CciLogParser.lil: buffer too small for conversion, " 
                       "pass only ASCII style messages");
    cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "cpiSetElementValue()", 
           constWBIMBCatalog, 3001, charBuffer, 
           charBuffer, CONST_VIRTUALTRACENODENAME, 0);             
  } else {
    // unhandled error
    sprintf(charBuffer, "CciLogParser.lil: unknown error rc=%i while retrieving the text", rc);
    cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "cpiSetElementValue()", 
           constWBIMBCatalog, 3001, charBuffer, 
           charBuffer, CONST_VIRTUALTRACENODENAME, 0);             
  }  

  return;
}


The implementation of cpiElementValue() is identical to the sample's implementation, so it is not repeated here.

As shown in Listing 4, after doing the usual processing -- adding the passed value to the message tree during the first IF-statement -- this implementation accesses the passed element string using the WMQI-function cpiElementCharacterValue(). Besides some error checks, the only processing here is to convert the Unicode text into a platform dependent string representation and pass the text to the WMQI-function cciLog() (marked bold in Listing 5). Unfortunately, cciLog() expects a message source and a message number. On Windows this message source is a Dynamic Link Library (DLL) containing these messages, on UNIX systems this is a XPG4 catalog. Additionally, the message will have to be provided to WebSphere MQ Integrator Broker also in a plain text format to enable the WebSphere MQ Integrator Broker command mqsiformatlog to translate the log entries into readable ones.

As this article does not focus on using cciLog(), I simply misused the WMQI message id 3001. An implementation of this plug-in parser that can be used in a production environment, requires at least the following extensions:

  • Provide an own message catalog containing the required message id.
  • Offer three message elements, one for each possible level (CCI_LOG_ERROR, CCI_LOG_WARNING and CCI_LOG_INFORMATION).
  • Handle strings longer than 1023 characters.

Using the plug-in parser functionality in ESQL

To access the plug-in parser's functionality, the parser class name must be used. I selected "CCILOG", so the ESQL path OutputRoot.CCILOG invokes the parser's functions, for example, SET OutputRoot.CCILOG.Msg="a test log entry" passes the text "a test log entry" to the parser.


Listing 5. Shows an improved implementation of the original ESQL program that was first introduced in Figure 1.
SET OutputRoot = InputRoot;
-- Enter SQL below this line.  SQL above this line might be regenerated, causing any
modifications to be lost. DECLARE pRefNet REFERENCE TO OutputRoot.XML.Bill.Net; IF (pRefNet IS NULL) THEN SET OutputRoot.CCILOG.Msg = 'OutputRoot.XML.Bill.Net value was NULL'; ELSE SET OutputRoot.CCILOG.Msg = 'OutputRoot.XML.Bill.Net value was >' || pRefNet || '<'; END IF; DECLARE pRefTax REFERENCE TO OutputRoot.XML.Bill.Tax; IF (pRefTax IS NULL) THEN SET OutputRoot.CCILOG.Msg = 'OutputRoot.XML.Bill.Tax value was NULL'; ELSE SET OutputRoot.CCILOG.Msg = 'OutputRoot.XML.Bill.Tax value was >' || pRefTax || '<'; END IF; DECLARE pRefGross REFERENCE TO OutputRoot.XML.Bill.Gross; IF (pRefGross IS NULL) THEN SET OutputRoot.CCILOG.Msg = 'OutputRoot.XML.Bill.Gross value was NULL'; ELSE SET OutputRoot.CCILOG.Msg = 'OutputRoot.XML.Bill.Gross value was >' || pRefGross || '<'; END IF; SET pRefGross = CAST(pRefNet AS DECIMAL) * CAST(pRefTax AS DECIMAL) + CAST(pRefNet AS DECIMAL); SET OutputRoot.CCILOG.Msg = 'New value for OutputRoot.XML.Bill.Gross >' || pRefGross || '<'; -- Clean Up the CCILOG message tree DETACH OutputRoot.CCILOG;

Observe that the message tree OutputRoot.CCILOG should be detached at the end of the ESQL program. WebSphere MQ Integrator Broker would fail writing the message to an output WebSphere MQ Queue, because the CciLogParser does not implement a working function to serialize the message tree. The sub element Msg which is used to pass the trace text to the plug-in parser is chosen arbitrarily, any other element name can be used.


Reading trace entries

There are two ways to access the trace entries:

  • WMQI User Trace: Set the level for the User Trace to normal or debug, for example, mqsichangetrace BROKER -e default [-r] -l normal
    Retrieve the entries using mqsireadlog and mqsiformatlog, for example, mqsireadlog BROKER -e default -o tempfile.xml mqsiformatlog -i tempfile.xml
    Ignore all entries of type "UserTrace", look for entries of type "Information" or "Error".
  • Syslog (Windows: Event Viewer): The trace entries are always written to the syslog.

All entries use the message id 3001, the name of the node in the message text is "CciLogParser - Extension for ESQL".


Reflection

Looking back at the initial example, the directory-based e-mail check could also be implemented using a plug-in parser. Checking an e-mail address could be invoked in ESQL using the following statements:

... SET OutputRoot.EMAILCHK.eMail = currentEMailAddress; IF (OutputRoot.EMAILCHK.IsValid = FALSE) THEN do some corrective code END IF; ...

... This plug-in parser would get the e-mail address in its implementation function cpiSetElementValue(), check the passed value using the directory server and set the element IsValid to TRUE or FALSE. This processing is more sophisticated than our simplified case study, but its general concept is the same.


Conclusion

This article described a new way of implementing additional functionality in WebSphere MQ Integrator Broker. For this, a simple case study was used to demonstrate the general concept of developing functionality by implementing plug-in parsers.

Nevertheless, the approach described here is not the way plug-in parsers were initially meant to be used. You should carefully evaluate whether your processing can be solved with conventional practice like plug-in nodes. However, in some situations plug-in parsers offer a solution for complex tasks.


Listing 6. Complete code listing
#ifndef __MVS__
  #include <malloc.h>
#endif
#include <windows.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <BipCci.h>
#include <BipCni.h>
#include <BipCpi.h>

#ifdef __cplusplus
extern "C" {
#endif

void LilFactoryExportPrefix * LilFactoryExportSuffix bipGetParserFactory(void);

#ifdef __cplusplus
}
#endif

#ifdef __MVS__
#define BIP_DEF_COMP_CCSID 1047
#else
#define BIP_DEF_COMP_CCSID 1208
#endif

#define CONST_PARSER_CLASS              "CCILOG"
#define CONST_PARSER_FACTORY            "ComIbmSampleCciLogParserFactory"
#define CONST_WBIMB_CATALOG             "WMQIv210"
#define CONST_VIRTUALTRACENODENAME      "CciLogParser - Extension for ESQL"

CciChar * constParserClass    = 0;
CciChar * constParserFactory  = 0;
CciChar * constWBIMBCatalog   = 0;

// -----------------------------------------------------------------------------
// Plugin Parser Implementation Function
//
//  the signature of cpiParseBufferEncoded() and cpiWriteBufferEncoded() is 
//  the same and their body is empty, so just this one function is used
int cpiParseAndWriteBufferEncoded(CciParser* parser, CciContext* context, 
                                  int encoding, int ccsid) {
  return 0;
}

// -----------------------------------------------------------------------------
// Plugin Parser Implementation Function
CciContext* cpiCreateContext(CciParser* parser) {
    return((CciContext*) 0);
}

// -----------------------------------------------------------------------------
// Plugin Parser Implementation Function
//
//  the signature of cpiParseFirstChild(), cpiParseLastChild(), 
//  cpiParsePreviousSibling() and cpiParseNextSibling() is the
//  same and their body is empty, so just this one function is used
void cpiParseFirstLastChildAndPreviousNextSibling(CciParser* parser, 
                                      CciContext* context, CciElement* element) {
  return;
}

// -----------------------------------------------------------------------------
// Plugin Parser Implementation Function
void cpiSetElementValue(CciParser* parser, CciElement* element, CciElementValue* value) {

  CciElement* valueElement;
  CciSize     bufferSize;
  int         rc;
  CciChar     buffer[1024]; // maximum supported length of message
  char        charBuffer[1024];

  // set the value
  valueElement = element;
  if ((cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_VALUE) ||
      (cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_NAME_VALUE))  {
    cpiSetElementValueValue(&rc, element, value);
  } else if (cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_NAME) {
    /* Create a new value element, add as a first child, and set the value */
    valueElement = cpiCreateElement(&rc, parser);
    cpiSetElementType(&rc, valueElement, CCI_ELEMENT_TYPE_VALUE);
    cpiSetElementValueValue(&rc, valueElement, value);
    cpiAddAsFirstChild(&rc, element, valueElement);
  }

  buffer[0] = 0;
  bufferSize = cpiElementCharacterValue(&rc, valueElement, buffer, 1023);

  if (rc==CCI_EXCEPTION) {
    cciRethrowLastException(&rc);
  } else if (rc==CCI_SUCCESS) {
    cciUcsToMbs(&rc, buffer, charBuffer, 1023, BIP_DEF_COMP_CCSID);
    if (rc!=CCI_SUCCESS) {
      // Error occured, e.g the message contained non-ASCII 
      // characters which were expanded to more than one byte per character.
      sprintf(charBuffer, "CciLogParser.lil: error converting the log text "
                          "into a C-string, error code %i", rc);
      cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "cpiSetElementValue()", 
             constWBIMBCatalog, 3001, charBuffer, 
             charBuffer, CONST_VIRTUALTRACENODENAME, 0);             
    } else {
      // the original intend of this parser; write the message to the WMQI log
      cciLog(&rc, CCI_LOG_INFORMATION, __FILE__, __LINE__, "cpiSetElementValue()",
             constWBIMBCatalog, 3001, charBuffer, 
             charBuffer, CONST_VIRTUALTRACENODENAME, 0);
    }
  } else if (rc==CCI_BUFFER_TOO_SMALL) {
    // here we could allocate a new buffer and retrieve the text again,
    // but this sample just writes an error to the log
    strcpy(charBuffer, "CciLogParser.lil: buffer too small for conversion, " 
                       "pass only ASCII style messages");
    cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "cpiSetElementValue()", 
           constWBIMBCatalog, 3001, charBuffer, 
           charBuffer, CONST_VIRTUALTRACENODENAME, 0);             
  } else {
    // unhandled error
    sprintf(charBuffer, 
            "CciLogParser.lil: unknown error rc=%i while retrieving the text", rc);
    cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "cpiSetElementValue()", 
           constWBIMBCatalog, 3001, charBuffer, 
           charBuffer, CONST_VIRTUALTRACENODENAME, 0);             
  }  

  return;
}




// -----------------------------------------------------------------------------
// Plugin Parser Implementation Function
const CciElementValue* cpiElementValue(CciParser*  parser, CciElement* element) {
  CciElement* firstChild;
  const CciElementValue* value;
  int         rc;

  if ((cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_VALUE) ||
      (cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_NAME_VALUE)) {
    value = cpiElementValueValue(&rc, element);
  }
  else if (cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_NAME) {
    firstChild = cniFirstChild(&rc, element);
    value = cpiElementValueValue(&rc, firstChild);
  }
  else {
  }

  return(value);
}

// -----------------------------------------------------------------------------
// utility function
const CciChar* CciString(const char* source, int codepage) {
  // maximum number of characters in Unicode representation
  int rc;
  int maxChars = strlen(source) + 1 ;
  CciChar* buffer = (CciChar*) malloc(maxChars * sizeof(CciChar));

  cciMbsToUcs(&rc, source, buffer, maxChars, codepage);
  
  return buffer;
}

// -----------------------------------------------------------------------------
// utility function
void initParserConstants(void) {
  constParserClass   = (CciChar*) CciString(CONST_PARSER_CLASS,   BIP_DEF_COMP_CCSID);
  constParserFactory = (CciChar*) CciString(CONST_PARSER_FACTORY, BIP_DEF_COMP_CCSID);
  constWBIMBCatalog  = (CciChar*) CciString(CONST_WBIMB_CATALOG,  BIP_DEF_COMP_CCSID);
}

// -----------------------------------------------------------------------------
// entry point for WMQI
void LilFactoryExportPrefix * LilFactoryExportSuffix bipGetParserFactory(void) {
  CciFactory*     factoryObject;
  int             rc;
  static CPI_VFT  vftable = {CPI_VFT_DEFAULT};

  // initialize the constants used by this plug-in
  initParserConstants();

  // setup function table with pointers to parser implementation functions
  vftable.iFpParseBufferEncoded       = cpiParseAndWriteBufferEncoded;
  vftable.iFpWriteBufferEncoded       = cpiParseAndWriteBufferEncoded;
  vftable.iFpSetElementValue          = cpiSetElementValue;
  vftable.iFpElementValue             = cpiElementValue;

  // mandatory functions, otherwise WMQI does not use this parser
  vftable.iFpCreateContext            = cpiCreateContext;
  vftable.iFpParseFirstChild          = cpiParseFirstLastChildAndPreviousNextSibling;
  vftable.iFpParseLastChild           = cpiParseFirstLastChildAndPreviousNextSibling;
  vftable.iFpParsePreviousSibling     = cpiParseFirstLastChildAndPreviousNextSibling;
  vftable.iFpParseNextSibling         = cpiParseFirstLastChildAndPreviousNextSibling;

  // create the parser factory for this plugin
  factoryObject = cpiCreateParserFactory(&rc, constParserFactory);
  if (factoryObject) {
    // Define the classes of message supported by the factory
    cpiDefineParserClass(&rc, factoryObject, constParserClass, &vftable);
  } else {
      static char* errMsg = "CciLogParser.lil: error creating the parser factory " 
                            CONST_PARSER_FACTORY;
      cciLog(&rc, CCI_LOG_ERROR, __FILE__, __LINE__, "bipGetParserFactory()",              
             constWBIMBCatalog, 3001, errMsg, errMsg, CONST_VIRTUALTRACENODENAME, 0);
  }

  return(factoryObject);
}


Resources

About the author

Martin Smolny works on the WebSphere Business Process Choreographer team in Boeblingen, Germany. He has worked on different IBM products and has seven years of experience in business integration software. Martin completed his studies of Information Technology in Stuttgart.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=14652
ArticleTitle=Extending WebSphere MQ Integrator Broker V2.1 and WebSphere Business Integration Message Broker V5
publish-date=07212004
author1-email=Martin.Smolny@de.ibm.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers