Skip to content

Simple JMS example with Glassfish and a RESTful webservice

by Matthias Fraass on November 8th, 2009

In this little tutorial, we will create a simple MessageDriven bean. It will consume messages which are produced in a simple way by a RESTful webservice.

Preparation

Setup Glassfish

Technorati-Tags: ,,,

You need a clean installation of Glassfish (v2 or v3). I also recommend an IDE with Glassfish integration. Netbeans should be easiest as I’ve heard that it’s got the best Glassfish integration, but I am using Eclipse 3.5. I won’t cover the setup process in your IDE – if you’re having difficulties, please let me know.

The few basic steps you need to do is:

  1. Install Glassfish (e.g. /dev/glassfishv3/)
  2. Setup Glassfish in Eclipse via Window->Preferences->Server->Runtime Environments and point it to /dev/glassfishv3/glassfish. The result should look like this:
    serverconfig
  3. Add the “Server” view if it doesn’t show up yet and add a new Server (RMB->New->Server):serverconfig2
    You should get a server entry and be able to start and stop the instance.

    serverconfig3
    Please verify if that works, first. Now you can start up Glassfish.

Configure Glassfish

Open a command prompt or terminal in /dev/glassfishv3/bin/ and be sure that Glassfish is running. Then create the JMS queues in glassfish (works with v2 and v3) with the asadmin tool:

asadmin create-jms-resource --restype javax.jms.ConnectionFactory jms/SimpleConnectionFactory
asadmin create-jms-resource --restype javax.jms.Queue jms/SimpleQueue</code>

The implementation

Now we need some code. We will use a MessageDriven bean to consume the messages and a RESTful webservice to produce them in a simple way. For the MessageDriven bean, create a “EJB project” (Eclipse: New -> Project -> EJB/EJB Project) and put the following class in there:

package de.tricoder.net.test.jms;

import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

/**
* Simle message driven bean.
*/

@MessageDriven(mappedName = "jms/SimpleQueue")
public class SimpleMessageDrivenBean implements MessageListener {

/**
* Default constructor.
*/

public SimpleMessageDrivenBean() {
}
/**
* @see MessageListener#onMessage(Message)
*/

public void onMessage(Message message) {
try {
System.out.println("Got message: " + ((TextMessage)message).getText() + " @" + System.currentTimeMillis());
} catch (JMSException e) {
e.printStackTrace();
}
}

simplejms1
Now we need a Web Project which contains the RESTful Webservice (Eclipse: New -> Project -> Web/Dynamic Web Project). Add the following class to that project:

package de.tricoder.net.test.jms;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.NamingException;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

/**
* Example of a RESTful webservice producing messages for a JMS Queue.
* Call via <a href="http://localhost:8080/webservicetest/jms">http://localhost:8080/webservicetest/jms</a>
* @author Matthias Fraass
*/

@Stateless // dependency injection won't work without that
@Path("/jms") // path appended to context root -&gt; <a href="http://localhost:8080/webservicetest/jms">http://localhost:8080/webservicetest/jms</a>
public class SimpleJMSRestfulWebService {

@Resource(mappedName = "jms/SimpleConnectionFactory") //= connection factorie's JNDI name
private ConnectionFactory connectionFactory;

@Resource(mappedName = "jms/SimpleQueue") //= Queue's JNDI name
private Queue queue;

/**
* Our RESTful webservice
*/

@GET
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public String putMessage() throws NamingException, JMSException, NotSupportedException, SystemException, SecurityException, IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException
{
System.out.println("called putMessage");
javax.jms.Connection  connection = connectionFactory.createConnection();
javax.jms.Session        session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(queue);
long start = System.currentTimeMillis();
int i=0;
do
{
TextMessage message = session.createTextMessage();
message.setText("Hello, JMS! #"+start);
messageProducer.send(message);
i++;
}
while (i &lt; 1000);
long now = System.currentTimeMillis();
return "JMS produced 1000 messages within " + (now-start) + "ms";
}
}

simplejms2

Now you need to configure the Jersey Servlet in web.xml, so that it picks up the WebService. Put the following in betwen the display-name and the welcome-file-list tags.

...
<display-name>JMS1web</display-name>

<servlet>
<servlet-name>Jersey Web Application</servlet-name></code>

<code><servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>

<init-param>

<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value>

</init-param>

<init-param>

<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>de.tricoder.net.test.jms</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>Jersey Web Application</servlet-name>

<url-pattern>/*</url-pattern>

</servlet-mapping>

<welcome-file-list>
...

This WebService will produce 1000 messages and output the time it took. We’ll use that to compare the performance of different distribution scenarios and message queue products during the course of the next articles.

Deployment

The last thing we need is the EAR project (New -> Project / JavaEE/Enterprise Application Project). Add the EJB and the Web project to the EAR project. The result will be:

simplejms3

You should now be able to deploy that in glassfish:

simplejms4

and then

simplejms5

The server.log (glassfish/domains/domain1/logs/server.log or in the Eclipse Console – be sure to switch to “server.log”) should output this:

...
INFO: DOL Loading time150

INFO: endpoint.determine.destinationtype
...
INFO: Portable JNDI names for EJB SimpleJMSRestfulWebService : [java:global/JMS1/JMS1web/SimpleJMSRestfulWebService, java:global/JMS1/JMS1web/SimpleJMSRestfulWebService!de.tricoder.net.test.jms.SimpleJMSRestfulWebService]
INFO: Unknown loader org.glassfish.internal.api.DelegatingClassLoader@11b92ef class org.glassfish.internal.api.DelegatingClassLoader
INFO: Scanning for root resource and provider classes in the packages:
de.tricoder.net.test.jms
INFO: Root resource classes found:
class de.tricoder.net.test.jms.SimpleJMSRestfulWebService
INFO: Provider classes found:
INFO: Initiating Jersey application, version 'Jersey: 1.1.0-ea 04/30/2009 06:59 PM'
INFO: Binding the EJB class de.tricoder.net.test.jms.SimpleJMSRestfulWebService to EJBManagedComponentProvider
INFO: Loading application JMS1#/C:/dev/glassfishv3/glassfish/domains/domain1/eclipseApps/JMS1/JMS1web_war/ at JMS1web
INFO: Deployment of JMS1 done is 992 ms

Then, point a browser to e.g. http://localhost:8080/JMS1web/jms/ and you should see “JMS produced 1000 messages within XYms” in your browser (doesn’t work with Chrome) The server.log should look like this:

INFO: called putMessage ..
INFO: Got message: Hello, JMS! #1257518116879 @1257518117079
INFO: Got message: Hello, JMS! #1257518116879 @1257518117089 ...

Vóila! Your first JMS enterprise project is running! It is using the internal OpenMQ instance of Glassfish, which is running on port 7676 by default. That’s not *remote* messaging yet, but it can already enable you to asynchronously process tasks. That’s good for most smaller projects or local development and testing We will use that simple example as a starting point for the following, more demanding ;) tutorials which will do remote messaging.

From → Coding

2 Comments
  1. Martin Theisen permalink

    wow, this helped me a lot. I have the same config and tools\Netbeans, but I wasn’t able to access the JMS queue via @get/post. In the end I want send XML data with REST and store it my queue.

    I started writing a small GUI as remote client which used a send and receive logic of a bean to access the queue. When adding the REST capability by putting the very same bean into a REST project, it stopped working. So I tried this fella:
    http://raulraja.com/2009/06/25/spring-exposing-a-bean-as-rest-xml-json-and-soap-webservice/
    who annotates a bean interface as REST. seemed more reasonable, but I couldn’t reproduce the program,
    Yours worked fine!

    cheers

Trackbacks & Pingbacks

  1. Simple JMS example using Glassfish and Netbeans « shr3y4s.com

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS