mq Authors: RealWire News Distribution, Charles Rich, Application Security, Daniel Thompson, Kevin Benedict

Related Topics: Java EE Journal, Apache Web Server Journal, mq

J2EE Journal: Article

Implementing J2EE/.NET Interoperability Using WebSphere MQ Part 2 - Putting theory into practice

Implementing J2EE/.NET Interoperability Using WebSphere MQ Part 2 - Putting theory into practice

In Part 1 of this series, we discussed how the use of messaging software can alleviate some of the problems with integration of J2EE and .NET environments using Web services. In this article we will discuss implementation of the proposed architecture on both J2EE and .NET platforms, along with possible enhancements of the proposed solution.

All of the code referenced in this article is available for download from

Implementing the .NET Client
Although support pack MA07 supports all the basic functionality of WebSphere MQ and is implemented based on the WebSphere MQ Java object model, implementation of interoperability with a JMS-based J2EE implementation poses the following challenges:
1.  Implementation of JMS for WebSphere MQ introduces the RFH2 header, which is used by this implementation to support JMS-required features (e.g., custom properties). Messages sent using the JMS implementation contain the RFH2 header. The .NET implementation, on the other hand, treats the RFH2 header as part of the message payload.
2.  Although there is standardized support for LDAP access in .NET, directory information for JMS is kept in the form of Java classes and cannot be interpreted by C# applications.
3.  In the case of request/reply communications, matching of the replies to the appropriate requests is required. The most common technique for this is for the client to read the WebSphere MQ message ID (guaranteed to be unique) after the message is sent, and for the server to read this ID from the request message and put it into the correlation ID field of the reply message. In this case, a client can determine the corresponding request message based on the correlation ID of the reply message.

The two options for correlation ID matching use either the builtin WebSphere MQ or programmatic support. WebSphere MQ support allows reading from the specified queue based on the correlation ID. In this case only the message with the predefined correlation ID is read from the queue.

This allows the client to send the message, get the message ID, and then do a blocking read with the timeout based on the correlation ID. The advantage of this approach is the programmatic simplicity. The drawback is that if the read times out, the message remains in the queue for a potentially long period of time. If the overall system performance slows down for some reason, the reply queue can start growing. This situation can be partially alleviated by limiting the "time-to-live" of the reply messages, thus implementing self-cleaning of the reply queue. This technique can be somewhat helpful, but it makes overall system monitoring more difficult because in this case messages disappear by themselves.

The first problem is solved by the creation of the JMSMessage class, derived from the MQMessage class, and encapsulating RFH2 header processing. Usage of the WebSphere MQ name resolution Web service solves the second problem. For the third problem, programmatic correlation is used.

We will begin by discussing the first two point solutions and then show how they are used in the overall client implementation.

As mentioned above, the introduction of LDAP allows for a central point of control for the overall WebSphere MQ infrastructure. The problem is that the only existing standard for the LDAP entries supported by JMS defines all entries as Java classes, thus making it very hard to access LDAP information from other languages.

Our solution for this problem exposes LDAP information through an HTTP Web service implemented in Java. This provides standardized access to the relevant LDAP information from any platform supporting HTTP Web services.

At first glance it may seem that using Web services for MQ object resolution defeats the purpose of our WebSphere MQ implementation. Instead of doing integration directly using Web services, we are now using Web services to resolve MQ objects, and then using MQ for the actual application's communications. In reality Web services are a supporting technology in this case, and their usage is fairly limited in our solution:

  • The amount of data transferred by Web services is limited to the information on the MQ objects. The performance of this service can be well defined.
  • Usage of caching, incorporated in our implementation, usually allows for minimizing overall Web services traffic.
  • Because only one centralized Web service is used in the overall system, this service can be optimized for high availability.
  • All of the quality-of-service aspects of the actual consumer-to-provider communications are defined by WebSphere MQ-based communications rather than by the Web services.

    As shown in Figure 1, the overall implementation is composed of two parts: implementation of the service itself, and implementation of the .NET client. This includes the Web service client itself, a caching mechanism, and an interface to the rest of the implementation.


    As mentioned earlier, the actual service is implemented in Java in the form of a JavaBean that exposes two methods:

  • MQData serviceLookUp (String servicename): This method retrieves the information about the producer WebSphere MQ environment, including request queue information as well as information about the producer queue manager. The reply is sent back within a single MQData structure in order to minimize the network traffic and the number of method invocations.
  • MQData consumerLookUp (String consumername): This method retrieves the information about the consumer WebSphere MQ environment, including reply queue information as well as information about the consumer queue manager. The reply is sent back within a single MQData structure in order to minimize the network traffic and the number of method invocations.

    Here MQData is the generic data structure class (see Listing 1) representing both queue and queue manager information. It is populated by the JNDILookUpUtil class (see Listing 2). The consumername or servicename string defines the consumer/ producer name in a standard JNDI format, i.e., /Path1/Path2/ Path3. The conversion to the complete JNDI location, along with the conversion to the format of the specific JNDI implementation, is done under the covers by a dedicated class called ServiceQueueString (see Listing 3). Usage of the standard JNDI format allows our implementation to support any JNDI implementation (LDAP-based, file-based, or WAS internal JNDI implementations are currently supported). Bean implementation (see Listing 4) is configurable through the configuration file (see Listing 5) containing the provider URL and the Initial Context Factory.

    Standard WSAD 5 Web services support was used to create the Web service from our JavaBean. The WSDL files generated by WSAD are presented in Listings 6-9.

    The service client is implemented as .NET class library. Our implementation uses the Web service proxies and MQData class automatically generated by Visual Studio .NET from the Service.wsdl and Binding.wsdl files produced by WSAD 5.0.

    Implementation includes the JNDIProxy and JNDICache classes. The JNDIProxy (see Listing 10) is used by any application that accesses the JNDI Web service. The following methods are exposed:

  • public MQData ProducerLookUp (string producername): This method returns an MQData structure that includes the information related to the producer WebSphere MQ environment. Only input queue information is used by the .NET client implementation.
  • public MQData ConsumerLookUp (string consumername): This method returns an MQData structure that includes information related to the consumer WebSphere MQ environment, including consumer queue manager information and consumer reply queue name.

    In order to limit the amount of communication between the JNDIProxy class and the JNDI Web service, each invocation result is stored (based on the consumer/ producer name) in the JNDICache class (see Listing 11). Before invoking the JNDI Web service, the JNDIProxy checks its cache to see whether or not an entry has already been processed. If the entry exists and is not too old (a reference is considered "old" when its lifetime exceeds three hours), then the proxy returns that value to the invoker. Otherwise, a Web service is invoked.

    IBM introduced the RFH2 header to support JMS-specific data. The RFH2 header is extensible and can also carry additional information that is not directly associated with JMS. For the purpose of our discussion, only JMS-specific usage of the RFH2 header is covered.

    The header is composed of two parts, one fixed, and the other variable. The fixed portion of the header contains such information as message format, encoding, flags, etc. The JMS-specific variable portion of the header can contain the following three folders:

  • The <mcd> folder: Contains properties that describe the shape or format of the message. For example, the Msd property identifies the message as being Text, Bytes, Stream, Map, Object, or "Null". This folder is always present in a JMS RFH2 header.
  • The <jms> folder: Used to transport JMS header fields and JMSX properties that cannot be fully expressed in the MQMD. This folder is always present in a JMS RFH2 header.
  • The <usr> folder: Used to transport any application-defined properties associated with the message. This folder is only present if the application has set some applicationdefined properties.

    Basic RFH2 processing is implemented by the RFH2 class, shown in Listing 12.

    The MA7P support pack being used for WebSphere MQ programming appends RFH2 content to the message payload. This means that the RFH2 content has to be extracted from the incoming message and appended to the outgoing one. This functionality is implemented by the JMSMessage class (see Listing 13). The interface for this class was modeled after the Message interface in JMS.

    Overall Client Implementation
    The overall WebSphere MQ communication client is implemented as a class library, exposing the RequestProcessor class (see Listing 14). This class exposes three methods to its users:

  • RequestProcessor getRequest Processor(string producer): This static method serves as a Request Processor factory, allowing for the creation of a new instance of the class, configured to communicate to the specific producer. Besides creating and returning the reference of the new RequestProcessor instance, this method ensures proper initialization of the MQ environment and other required classes. Configuration parameters for a particular instance are retrieved from the Config.config file (see the sample config file shown in Listing 15), which has to be located in the same directory as the client application itself. The ConfigurationParameters class (see Listing 16) is used to read and process configuration parameters. The set of configuration parameters includes:
    -wsURL: The URL for the Web service, which supports JNDI lookups.
    -name: The name of the client. This value is used to request MQ environment information from the JNDI lookup Web service.
    -receiverThreads: The number of threads that the MessageReceiver class will run. The getRequestProcessor method also ensures that the message receiver is correctly initialized. It uses the JNDI lookup Web service to obtain information about the queue that the producer is listening on.

  • string requestReply(string message, int timeout): This method executes request/reply (blocking) for the producer defined in the factory method. It takes two parameters - request message (string) and timeout (in milliseconds). It returns a reply message (string) or, if communication fails, throws an exception.
  • void fireAndForget(string message): This method sends a request to the producer defined in the factory method and immediately returns. It takes a single parameter - request message (string). The method throws an exception if the sending of a message fails.

    Two classes implement the actual WebSphere MQ communications:

  • MessageSender: This class (see Listing 17) is a straightforward implementation of the MQ message sender with the following caveats:
    -Because in .NET implementation of the MQQueueManager object is not transferable between threads, it is necessary to create a new instance of this object (MQ connection) on each thread (for each instance of the class).
    -In the case of fire-and-forget, persistent messaging (the default) is used. In the case of request/reply we use nonpersistent messages (which results in significant performance improvement). Also, in this case we are setting an expiration time for messages (making the queue self-cleaning).
    -We are using our own coordination (described below) to coordinate between request and reply messages.

  • MessageReceiver: This class (see Listing 18) is a multithreaded implementation of the message receiver.

    Coordination between MessageSender and MessageReceiver is implemented using two classes:

  • DataRetriever: This class (see Listing 19) supports dual functionality:
    -Data transfer between sender and receiver threads. This is done through the private reply object, which is set by the receiver thread and read by the sender thread.
    -Synchronization between sender and receiver threads, based on the Monitor object (standard synchronization support in .NET).

  • Correlator: This class (see Listing 20) is a thread-safe wrapper around a standard hashtable class (not thread-safe in .NET). A unique message ID/correlation ID, generated by MQ and set by the provider implementation, is used as a key between sender and receiver threads.

    Implementing the J2EE-Based Server
    There are many approaches to implementing a J2EE-based consumer using messaging. We have chosen a message-driven bean (MDB)-based implementation of the producer.

    A standard pattern for implementing applications using MDBs is to make the MDB implementation responsible for messaging and invoking a stateless entity bean for the actual message processing (business functionality). Due to the extreme simplicity of our implementation, we are not following this practice, but rather implementing a separate method on the same bean for the actual processing. The functionality of this method is fairly straightforward: it takes a string from the incoming message and appends it to the "Hello" string. It then sends a response back using the ReplyToQ information specified by the consumer.

    WSAD v5 tooling was used for the generation of the MDB itself, and the required additional functionality was added manually. The MDB code is shown in Listing 21. After its creation, the MDB must be associated with the listening port (see Figure 2).


    In order to deploy the MDB, the following must be done:

  • WAS messaging must be configured to define the queue and queue manager that the MDB is listening on.
  • The listener port must be configured, tying this bean to the queue/ queue manager definition created in the previous step.

    Configuration of the queue/queue managers' information is done through the administrative console client. WAS v5 allows three different JMS "provider" configurations for messaging:
    1.  WebSphere JMS provider: A simple, internal JMS server provided with WAS for messaging to support the J2EE 1.3 requirement for messaging. All configuration for this can occur within the WAS admin console (or WSAD). The JMS JNDI entries are defined in the WebSphere JNDI namespace.
    2.  WebSphere MQ JMS provider: Alternatively, you can continue to use WebSphere MQ for messaging. The administration of this is greatly improved in WAS 5, because all configuration for this provider can occur within the WAS admin console (or WSAD). The JMS JNDI entries in this case have to be defined in the WebSphere JNDI namespace.
    3.  Generic JMS provider: An alternative that allows the ability to configure external providers for JMS messaging, including the use of external JNDI registries for the JMS entries. External messaging server providers are also provided.

    The use of an external LDAP directory in our architecture implies usage of a generic JMS provider. Use of a generic provider requires definition of the following:

  • Provider name
  • JAR files used by our JMS provider (in our case, the WebSphere MQ JAR files)
  • Native library path used by our provider (WebSphere MQ path)
  • External context factory (in our case LDAP) and the LDAP provider URL

    The configuration screen for a generic messaging provider is shown in Figure 3.


    In addition, resources (i.e., queues and queue connection factories) must be defined in order for the provider to work.

    The producer queue is defined by creating a "JMS Destination," which can be set as one of our generic JMS provider properties. The process consists of defining a local JNDI reference, mapping it to an LDAP entry, and specifying the type of the entry (i.e., Queue or Topic). In our case we are defining a queue type. A sample JMS destination screen is shown in Figure 4.


    Similarly, a queue connection factory must be defined for a generic JMS provider, including local JNDI reference, external reference, and type (queue, in our case). A sample JMS queue connection factory screen is shown in Figure 5.


    Once the JMS destinations and the JMS connection factory are defined, we can then define the input port used by our MDB implementation to pull the messages out of the queues.

    Testing Our Implementation
    In order to verify that our implementation works correctly, we created a very simple C# client application (see Listing 22) using our .NET client implementation. This client contains a simple form (see Figure 6) that contains two text boxes (one for entering a request and another for displaying the response), two labels, and a button for submitting the request to the MQ Client. Our implementation was generated automatically by Visual Studio .NET, except for the Sbutton_Click(object sender, System.EventArgs e) method implementation. This method invokes our MQ client to synchronously invoke the J2EE-based provider. The result of the test client execution is shown in Figure 7.



    Additional Options for Using Web Services Over MQ
    The example presented here describes only basic WebSphere MQ-based messaging implementation between .NET-based and J2EEbased application servers. Real-life implementations should consider messaging formats between applications. One of the most ubiquitous data communications standards today is SOAP, which is supported extremely well by both .NET and J2EE application servers. A completely revised version of IBM's support pack - MA0R ( supportpacs/individual/ma0r.html) - addresses just that. This support pack provides an implementation for both the .NET and J2EE sides to implement SOAP over MQ using Web services interfaces.

    The .NET implementation is based on the overwriting of the .NET class ApplicationHost, enabling the host to create application domains for processing ASP.NET requests by a specialized implementation supporting both HTTP and WebSphere MQSeries requests. In the case when .NET acts as a service producer, this implementation provides both MQ and HTTP listeners that allow for the receiving of SOAP messages using either transport, and invoking a .NET SOAP-processing pipeline for processing of incoming SOAP messages. If .NET is used as a service consumer, the provided implementation uses either MQ or HTTP transport for request/reply messages based on the URL of the service.

    The J2EE implementation is based on Axis ( from the Apache foundation and supports WebSphere MQ (JMS). Combining an AXIS server with the MDB implementation described here allows a J2EE server to effectively receive and process SOAP messages over MQ. Based on the Web service URL, an Axis-based client can use either HTTP or JMS as a client.

    Usage of SOAP over MQ for .NET/J2EE interoperability allows combining standards-based Web services with the MQ messaging infrastructure widely used in many companies today.

    Selecting WebSphere MQ as an interoperability solution between .NET and J2EE-based application servers allows the leveraging of a proven technology that already exists in many enterprises. In comparison with the Web services approach, the MQ-based solution provides the following advantages:

  • Reliable messaging
  • "Out of the box" support for asynchronous messaging (not described in this article) that allow for interactions with temporarily unavailable applications
  • Simpler scalability implementation through producer implementation "cloning" and MQ clustering (not described in this article)
  • Better application decoupling

    Usage of MA07, although not currently supported by IBM, provides support for the merging of Web services technology with reliable messaging that leverages a widely adopted, standard, rich communication paradigm over a wellestablished, reliable transport.

    We are thankful to our colleagues at CNA and IBM, especially Matt Segvich, Vallish Shankar, Gerald Daus, and Deborah Shaddon for their help in putting together this article and supporting code.

  • More Stories By Boris Lublinsky

    Boris Lublinsky is an Enterprise Architect at CNA Insurance where he is involved in design and implementation of CNA’s integration strategy, building application frameworks and implementing service-oriented architecture for the company Prior to this he was Director of Technology at Inventa Technologies, where he was overseeing and actively participating in engagements in EAI and B2B integration implementations and development of large-scale web applications. While a Technical Architect at Platinum Technology and SSA, Boris was involved in component-based systems development and design and implementation of execution platforms for component-based systems. In all, he has over 25 years experience in software engineering and technical architecture.

    Comments (2) View Comments

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.

    Most Recent Comments
    Tony Bermudez 01/17/05 02:32:30 PM EST

    Where is the complete source code? The listings is cut off.

    Cecilia Hamilton 05/03/04 06:03:05 PM EDT

    I was going to try the example, but the source code for the ejbremove ends very abruptly...

    public void ejbRemove() {

    private void sendReply(String data, Queue dest, String correlID) {

    Hashtable env = new Hashtable();

    String providerURL = "ldap://, cn=localhost";
    String InitialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
    String qcf = "cn=queueManager,cn=helloproducer,cn=Producers";
    QueueConnectionFactory factory;
    QueueConnection connection;
    QueueSession session;
    QueueSender sender;