Friday, August 27, 2010

How to create a Message Driven Bean in EJB 3 (Step by Step). Using RAD 7.5 and Websphere 7.0


In an enterprise application it is common to use asynchronous messaging. It is useful when you have to deliver a message (even if the destination is down) and you do not wait for a response in real time. In Java, we’ve got the JMS (Java Messaging Service) to work with asynchronous messaging.

JMS belongs to the Java Enterprise Platform since previous EJB version, however in EJB 3, the process to create a JMS component is much easier.

Basically, we can create a JMS component using the annotation @MessageDriven and also implementing the interface java.jms.MessageListener.

Although Message Driven Beans are simple to be created in EJB3, you should not use it for ALL situations. You should not use Message components when you need:

  • Real time response
  • The order of the requests are important
  • You need a synchronous request/response

Downloading Rational Application Developer 7.5 - Open Beta

In this article, we’re going to use the newest Rational Application Developer 7.5 - Open Beta. You can download it directly from its official website.

We’re going to use that version because RAD 7.5 has support for EJB3 component, as long as the RAD 7.0 (stable version) has not. However, you can test your JMS component in RAD 7.0 as well, but you will have to create the configuration file (.xmi) yourself manually.

Creating an Enterprise Application Project into RAD 7.5

Open the RAD 7.5 and go to the Java EE Perspective. Now, open the menu File -> New -> Enterprise Application Project. On the first screen, put the EAR project, in my case I’ve used TestJMS and click on Next.

On the next screen, check in the Generate Deployment Descriptor and click on New Module button. Check out theApplication client module and Connector Module. Hence we’re going to use only the EJB module and Web module. Click on Finish button and the EAR project, as well as the EJB and Web module are going to be created.

Creating the Message Driven Bean component

Let’s create our Message Driven Bean component using the @MessageDriven annotation. For a simple example, let’s create a single method that prints out a message on the screen coming from the client.

RAD 7.5 brings a wizard to create the MDB, so let’s use it.

Right mouse click on the TestJMSEJB -> New -> Message-Driven Bean. On the screen that will come up, fill up theJava Package, Class Name, Destination name, JMS and Destination type.

Click on Finish button and the Message Driven Bean will be created into jms package. Also, implement the method onMessage() like below:

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
@MessageDriven(activationConfig = { 
@ActivationConfigProperty(propertyName = "destinationType",          
 propertyValue = "javax.jms.Queue" ) },
 mappedName = "jms/messageQueue" )
public class ConsumerBean implements MessageListener {
    public void onMessage(Message message) {
 if (message instanceof TextMessage) {
            TextMessage text = (TextMessage) message;
           try {
                System.out.println(text.getText());
            } catch (JMSException e) {
                e.printStackTrace();
         }
        }
    }

}


As you can see, the code is really simple. Test if the object is a javax.jms.TextMessage, if so, prints out its content.

It’s done, our Message Driven Bean component has been created and implemented, simple huh? Now, it is time to configure the JMS Provider into Websphere. Also, we need to setup the destination of the message.

Setting up the JMS Provider and the Destination

It’s time to setup the configuration from the server side. This setup is made only once and usually it is responsability from EJB Deployer.

Certainly, the most famous JMS Provider is the IBM MQ Series, however for this example, we’re going to use a simplest JMS Provider. Websphere Application Server 6.1 brings an own JMS Provider itself, let’s use it.

Creating the Service Integration BUS (SIB)

Run the Websphere Application Server (you can do that through the Server Perspective, right click on WAS -> Start) and open its Administrative Console (right click on WAS -> Administration -> Run Administrative console). There, go to the MENU Service Integration and click on Buses.

  • On the buses screen, click on New button.
  • Next, insert the name MDBBus and then click Next and Finish.
  • Back to the Buses screen, click on Save link and then the MDBus will be created and committed.

Now, click on MDBBus link to open a new screen.

We’re going to use the three links on the right side. The first one is the Bus Member. Click on it.

On the next screen, click on Add button. Choose the first option Server.

  • Click on Next
  • choose File store and Next again.
  • On third screen, change the values: Log size: 10, Minimum permanent store size: 20, Maximum permanent store size: 50,
  • Click on Next button, Finish and Save link.

Now, let’s create the Destionations. Go back to the MDBBus screen and click on Destinations link.

  • Click on New button
  • Select Queue and click on Next
  • Enter: MDBQueue as Identifier. Also, click on Next.
  • Click on Next again.
  • Finally, click on Finish.

The SIB (Service Integration Buses) is created. The next step is to create the JMS Provider. Let’s do it.

Creating the JMS Provider

Go to the menu Resources -> JMS -> JMS Providers. On the center screen, click on Default messaging provider.

On the Default messaging provider screen, let’s create the Queue connection factory, Queue and the Activation Specification.

Creating the Queue Connection factory

Click on Queue Connection factories link. On the new screen, click on New button.

On the new screen, fill up the following fields:

  • Name (MDBQueueCF)
  • JNDI name (jms/messageCF)
  • Bus name (MDBBus)

Click on Ok button and then Save link.

Creating the Queue

Click on Queue link and then New button. On the new screen, fill up the following fields:

  • Name (MDBQueue)
  • JNDI name (jms/messageQueue)
  • Bus name (MDBBus)
  • Queue name (MDBQueue)

Click on Ok button and then Save link.

Creating the Activation specifications

Click on Activation specifications link and then click on New button.

On the new screen, fill up the following fields.

  • Name (MDBActivationSpec)
  • JNDI name (jms/activationSpec)
  • Destination type (Queue)
  • Destination JNDI name (jms/messageQueue)
  • Bus name (MDBBus)

Click on OK button and then Save link.

Both SIB and the JMS Provider were setup. Make sure to restart the Websphere server before continue this article.

Setting up the Websphere Deployment Descriptor (on EJB Project).

So far, we have created the Message Driven-Bean component, as well as the required configuration into Websphere Application Server. There is a simple setup yet. This setup will be made into Websphere Deployment Descriptor.

Right click on EJB Module (TestJMSEJB) and go to the option Java EE -> Generate Websphere Bindings Deployment Descriptor.

After this operation, a file called “ibm-ejb-jar-bnd.xml” will be created into ejbModulo/META-INF directory.

Double click on it to edit it. On the design section:

  • Click on Add button
  • Select Message Driven
  • Insert the name ConsumerBean
  • Select Message Driven and click on Add button again
  • Select JCA Adapter
  • Insert jms/activationSpec into Activation Spec Binding Name
  • Insert jms/messageQueue into Destination Binding Name.

The Websphere Deployment Descriptor setup is done. Let’s create the JMS client now.

Creating the Web Module to be the JMS Client

Now it is time to play around the Web Module we have created early.

The first think to do is to setup the Resources. To do that, double click on Deployment Descriptor.

On the new screen, go to the References tab. Click on Add button and follow the steps:

  • Select Resource reference.
  • Name: jms/messageQueueCF Type: javax.jms.QueueConnectionFactory Authentication: Container click on Okbutton.
  • JNDI name: jms/messageQueueCF.

Repeat the same process, but now using the following values:

  • Select Resource reference.
  • Name: jms/messageQueue Type: javax.jms.Queue Authentication: Container click on Ok button.
  • JNDI name: jms/messageQueue.

Creating the Servlet

Finally, let’s create a servlet that will be client of our example. Actually, the servlet will send out a text message to the JMS Provider. Our Message Driven-Bean will consume this message and print out into the console. See the servlet’s code below:

package servlets;

import java.io.IOException;

import javax.annotation.Resource;

import javax.jms.JMSException;

import javax.jms.MessageProducer;

import javax.jms.Queue;

import javax.jms.QueueConnection;

import javax.jms.QueueConnectionFactory;

import javax.jms.QueueSession;

import javax.jms.Session;

import javax.jms.TextMessage;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class JMSProducerServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

@Resource(name="jms/messageQueueCF" )

private QueueConnectionFactory qcf;

@Resource(name="jms/messageQueue" )

private Queue queue;

/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

try {

QueueConnection connection = qcf.createQueueConnection();

QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

MessageProducer producer = session.createProducer(queue);

TextMessage message = session.createTextMessage();

message.setText("#### JMS Example Running #####");

producer.send(message);

session.close();

connection.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

}

There is nothing special in the code above. We injected both Queue Connection Factory and the Queue to our Servlet, we started a QueueSession and sent out the TextMessage.

To run this code, right click on Servlet and go to Run As -> Run on Server. Select Websphere 6.1 and the code will be performed.

Look at the Console view, because when Message Driven Bean consume the message, it will prints out the result on the console, like image below.