2011/05/04
4 May, 2011

Communicating with WSO2 App Server via JMS

  • Manisha Eleperuma
  • Software Engineer - WSO2

Applies To

WSO2 Application Server 4.0.0
ActiveMQ 5.3.1

Contents

Introduction
JMS Configuration for AS
Real World Scenarios

Introduction

JMS is a standard protocol for reliable enterprise messaging offering:

  • asynchronous messaging - A JMS broker can deliver messages to a client as the messages arrive, without any special request made by the client in order to receive them
  • reliable messaging - JMS messaging ensures that a message is delivered only once with respect to one request.

In a communication channel, distinct endpoints may work with different protocols. The challenge of transforming message protocols is taken up by message brokers. Therefore, the sender or the receiver is freed from the hassle of knowing each other's endpoint's communication medium.

The WSO2 Carbon framework supports establishing such JMS connections with brokers such as Apache ActiveMQ. This capability is available in every WSO2 product, but with slightly different configurations. Except that, following a similar procedure with the WSO2 product in question, one can easily set up a JMS client communicating with an HTTP server or vice versa.

In this article, we will first look at a use case where a JMS client communicates with an HTTP enabled server. Its client will initially talk to the JMS Queue on ActiveMQ. From there, the message will be directed to the server's respective service. We have selected WSO2 Application Server as our deploying environment for this example.

JMS Configuration for AS

  • Step 1

Download the latest version of AS from here. Extract the downloaded binary distribution to a preferred location of your file system. We will refer to it as AS_HOME.

  • Step 2

Download Apache ActiveMQ 5.2.0 from here. Extract the downloaded distribution to a location in your file system. We will call it ACTIVEMQ_HOME.

  • Step 3

First, start the ActiveMQ broker and go to the ACTIVEMQ_HOME/bin directory in a terminal. Then, execute the script 'activemq'. In Linux, you have to give the command as 'sh activemq'. This will activate the JMS broker with the following status message log:

        INFO  TransportServerThreadSupport   - Listening for connections at: tcp://localhost:61616
	INFO  TransportConnector             - Connector openwire Started
	INFO  TransportServerThreadSupport   - Listening for connections at: ssl://localhost:61617
	INFO  TransportConnector             - Connector ssl Started
	INFO  TransportServerThreadSupport   - Listening for connections at: stomp://localhost:61613
	INFO  TransportConnector             - Connector stomp Started
	.......................................
	.......................................
	INFO  TransportConnector             - Connector vm://localhost Started

More information on starting ActiveMQ on other platforms can be found here.

  • Step 4

Now the Carbon server should also be enabled with JMS. To achieve this, copy the following .jar files, which reside in ACTIVEMQ_HOME/lib to the AS_HOME/lib/core/WEB-INF/lib directory.

  • activemq-core-5.2.0.jar
  • geronimo-jms_1.1_spec-1.1.1.jar
  • geronimo-j2ee-management_1.0_spec-1.0.jar

Following this, modify axis2.xml  in the Application Server (AS_HOME/repository/conf/axis2.xml) in such a way that the server is configured to JMS transport.

The JMS listener or the JMS transport Receiver configuration should be as follows:

<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener"> 
<parameter name="myTopicConnectionFactory"> 
<parameter name="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter> 
 <parameter name="java.naming.provider.url">tcp://localhost:61616</parameter> 
<parameter name="transport.jms.ConnectionFactoryJNDIName">TopicConnectionFactory</parameter> 
</parameter> 

<parameter name="myQueueConnectionFactory"> 
<parameter name="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter> 
<parameter name="java.naming.provider.url">tcp://localhost:61616</parameter> 
<parameter name="transport.jms.ConnectionFactoryJNDIName">QueueConnectionFactory</parameter> 
 </parameter> 

<parameter name="default"> 
<parameter name="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter> 
 <parameter name="java.naming.provider.url">tcp://localhost:61616</parameter> 
 <parameter name="transport.jms.ConnectionFactoryJNDIName">QueueConnectionFactory</parameter>
</parameter> 
 </transportReceiver>

These configurations will allow the use of the JMS Transport of the WSO2 AS with Apache ActiveMQ JMS broker.

  • Step 5

Start the WSO2 AS, done by running sh wso2server.sh within the AS_HOME/bin directory in a terminal. If you have successfully configured the WSO2 AS, you should see the following lines being printed on your console as the log:

    [2011-03-13 12:26:37,931]  INFO {org.apache.axis2.transport.jms.JMSSender} -  JMS Sender started
    [2011-03-13 12:26:37,932]  INFO {org.apache.axis2.transport.jms.JMSSender} -  JMS Transport Sender initialized...
    ... 
    [2011-03-13 12:26:40,406]  INFO {org.apache.axis2.transport.jms.JMSConnectionFactory} -  JMS ConnectionFactory : myTopicConnectionFactory initialized
    [2011-03-13 12:26:40,407]  INFO {org.apache.axis2.transport.jms.JMSConnectionFactory} -  JMS ConnectionFactory : myQueueConnectionFactory initialized
    [2011-03-13 12:26:40,408]  INFO {org.apache.axis2.transport.jms.JMSConnectionFactory} -  JMS ConnectionFactory : default initialized
    [2011-03-13 12:26:40,408]  INFO {org.apache.axis2.transport.jms.JMSListener} -  JMS Transport Receiver/Listener initialized...
    ...
    
    

This ensures that the JMS transport has successfully started by connecting to the ActiveMQ broker. When the AS has fully started up it will print a info log as shown below:

    [2011-03-13 12:26:56,216]  INFO {org.wso2.carbon.core.internal.StartupFinalizerServiceComponent} -  WSO2 Carbon started in 37 sec

Log in to AS and navigate to the Manage menu. Under Services, you will see the List menu. Go to List, then a list of deployed services will be displayed. There you will see various services. Click on any service and you will be directed to that particular service's dashboard.

Let's take the Version service. Under Endpoints, you will see the following endpoint:

 jms:/version?transport.jms.DestinationType=queue&transport.jms.ContentTypeProperty=Content-Type&java.naming.provider.url=tcp://manisha:61616&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory 

This confirms that the Version service is now exposed over JMS transport as well, after the above configurations.

Now you should be able to communicate via JMS to the WSO2 Application Server.

Real World Scenarios

Try it on your own and see how the JMS broker works with Application Server. What you need to do is create a message client that communicates with the JMS broker and do the above configurations. This will facilitate a JMS remote client to talk to a Carbon server. Where the service was only exposed through HTTP/HTTPS before, it is now exposed in JMS. From here, enable it to work with WSO2 AS 4.0.0. 

As shown in the image below, the JMS transport will be taken care of by the JMS broker. (Also, if the service is not exposed in JMS, the client can do a general HTTP/S GET request from the service deployed in the AS. )

First, follow the above actions and configurations shown in Steps 1-4. Then, create a client that will talk to the AS. To generate the client, go to AS_HOME/bin from a console. From there type the following command to generate a client stub. We will do this for the Version service available in AS. In a console, give the following command:

sh wsdl2java.sh -uri https://localhost:9763/services/version?wsdl out -uw

This will generate the client stub in the directory AS_HOME/bin/out.

Or else you can go to the Version service, from the service listing of AS and click on the 'Generate Client' option there. Tick only on the unwrapping(uw) command. This too will generate a client stub for you in your preferred directory.

Now, you can import these generated stub classes to any IDE that you prefer. You can create a project in Eclipse using the generated Build.xml or import it to IntelliJIDEA using the built pom.xml

Now, write a client in the project that you created importing the stub classes. A sample client will be as below:

package org.apache.ws.axis2;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import java.rmi.RemoteException;

public class JMSClient {

   public static void main(String[] args) throws AxisFault {
      ConfigurationContext cc = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null,
      "/home/manisha/program_Files/wso2appserver-4.0.0/bin/client/repo/axis2.xml");
      String url = "jms:/version?transport.jms.DestinationType=queue&transport.jms." +
      ContentTypeProperty=Content-Type&java.naming.provider.url=tcp://manisha:61616&java.naming.factory." +
      "initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&transport.jms." +
      "ConnectionFactoryJNDIName=QueueConnectionFactory";
      VersionStub stub = new VersionStub(cc, url);
      try {
        System.out.println("====Connected to App Server====");
        System.out.println("\t"+stub.getVersion());
        System.out.println("===============================");
      } catch (RemoteException e) {
        e.printStackTrace();
      }
}

We need to enable JMS on the client side too. Therefore, create a client repository (Just create a directory as AS_HOME/bin/client/repo/ and copy axis2.xml there). Make sure to enable JMS transportReceiver and TransportSender in client's axis2.xml.

Run the created client. You will get the response back with axis2 version as follows.

 ====Connected to App Server====
       WSO2 AppServer-4.0.0
 ==============================

Similarly you can try this out with any service that can be deployed in AS and access them with a JMS client via a JMS broker.

In most real world scenarios, the above communication takes place through a firewall proxy. The following two images depicts different instances that JMS communication occurs via a proxy.

This is an example of a user that uses JMS and requests an HTTP service deployed in an AS. Here, the proxy service should be exposed via JMS and a transformation occurs within the ESB where JMS is transformed into an HTTP request and sent to the AS. When the proxy gets hit with the AS's response in HTTP, it translates it to JMS and sends it back to the client.

Here, the Enterprise Service Bus's (ESB's) axis2.xml needs to be configured to send and receive JMS requests and responses.

The above image displays how a client uses HTTP requests to access a service that is exposed in JMS via a proxy. Here also the transformations of HTTP to JMS and vice versa takes place inside the ESB proxy. This is an instance where AS should be configured to send and receive JMS request and responses.

Likewise you can simply bridge any complex communication network with heterogeneous transport protocols via this simple configuration.

Author:

Manisha Eleperuma

Business Analyst; WSO, Inc.

[email protected]

 

About Author

  • Manisha Eleperuma
  • Software Engineer
  • WSO2 Inc