Sunday, May 19, 2013

Exposing JMS queue via JAX-RS Service

Today I am going to show you how to expose a JMS queue as a JAX-RS Service. Here I am using few tools for this.
  1. WSO2 Developer Studio 3.0.0
  2. WSO2 Application Server 
  3. Apache ActiveMQ
Here I am assuming that the Apache ActiveMQ up and running. You can start ActiveMQ with its management console (using the command ./activemq console) and view the queue details using from URL http://localhost:8161/admin/queues.jsp. Here is an screenshot the list of queue in my ActiveMQ server. Here I have one queue, SampleStockQuoteProvider with three messages in it.



You can view the content and other metadata of those messages by clicking the queue name. Following figure shows an example.


Now let's start with creating the JAX-RS service. Here I am using WSO2 Developer Studio where you can download from here.

Unzip the pack and start it as it is normal Eclipse IDE.
Then click on Developer Studio ---> Open Dashboard to get the Developer Studio dashboard. You can see a dashboard like below.


Now click on JAX-RS Service Project and create a project by filling the details as below.


Developer Studio will create a template project for you. Since we are going to access ActiveMQ within this service we need to add some dependencies.
To do that open the pom.xml file and add the following to the dependencies.

        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-core</artifactId>
            <version>5.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jms_1.1_spec</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.ws.commons.axiom</groupId>
            <artifactId>axiom-api</artifactId>
            <version>1.2.14</version>
        </dependency>


Now we can edit the DequeueService to consume the JMS queue in Apache ActiveMQ. Following is sample java code which I wrote.

package org.wso2.carbon.sample.dequeu.rest.service;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.xml.stream.XMLStreamException;

@Path("/dequeue/")
public class DequeueService {

    @GET
    @Path("{queueName}")
    @Produces(MediaType.APPLICATION_XML)
    public String dequeue(@PathParam("queueName") String queueName) throws Exception {
        System.out.println(queueName);
        Connection conn = null;
        Session session = null;
        MessageConsumer consumer = null;
        try {
            ConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
            conn = factory.createConnection();
            conn.start();
            session = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
            Destination queue = session.createQueue(queueName);
            consumer = session.createConsumer(queue);
            Message message = consumer.receive(1000);

            if(message == null) {
                throw new Exception("No message available in the queue");
            }

            message.acknowledge();
            return ((TextMessage)message).getText();
        } catch (JMSException e) {
            throw new Exception("Dequeuing not succeeded" ,e);
        } catch (XMLStreamException e){
            throw new Exception("Unexpected message found in the queue", e);
        } finally {
            if (consumer != null){
                consumer.close();
            }
            if (session != null) {
                session.close();
            }
            if (conn != null) {
                conn.close();
            }
        }
    }
}
[NOTE] Here I use the return mediatype as xml since messages in the queue I am going to pull has xml content. Instead you can use any mediatype listed in javax.ws.rs.core.MediaType.

Now you can go to the project home and build it using Maven using the command mvn clean install. It will create a web archive (WAR file) in the target folder. Now we need to deploy it in a Application Server, here I am going to use the WSO2 Application Server. Before deploying it, we need to add the dependency jars. So add the following list of jars (you can find them inside the ActiveMQ library) to the $CARBON_HOME/repository/components/lib. No need to restart the Application Server, these jars will be hot deployed.
  • activemq-core-5.7.0.jar  
  • geronimo-j2ee-management_1.1_spec-1.0.1.jar  
  • geronimo-jms_1.1_spec-1.1.1.jar  
  • hawtbuf-1.9.jar
Now log into WSO2 Application Management console on default URL https://localhost:9443/carbon and using the default username and passwords admin, admin. Then add the web application we just created. It will take 2-5 seconds and then it will appear on the deployed web application list as below.



Now the dequeuing JAX-RS service is ready to use. When you send a http GET request  to http://localhost:9768/JMSDequeueService/services/dequeue_service/dequeue/SampleStockQuoteProvider , you will get the top message of the queue, SampleStockQuoteProvider.




2 comments:

  1. hi
    How to Configure wso2 MB and wso2 AS servers , how to create simple jms example using MB and AS pleas add new post....

    ReplyDelete
  2. Hi Don, You just need to uncomment the JMS listeners in $CARBON_HOME/repository/conf/axis2/axis2.xml. I'll make another post in near soon.

    ReplyDelete