Message Driven Beans (MDB) using Seam and EJB 3.0

In my previous post, JMS Messaging with Seam, I showed you how to setup a queue and send a message to that queue using Seam. Now it is time to read that message from the queue and do something with it. As you guessed, it is very simple to do when using Seam and EJB 3.0.

The code below shows how to read a text message from the queue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package osbi.achs.messaging;

import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import javax.ejb.ActivationConfigProperty;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.log.Log;

@MessageDriven(name = "SearchQueueListenerBean", activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "/queue/achsSearch") })
public class SearchQueueListenerBean implements MessageListener {
  @Logger
  private Log log;

  @Override
  public void onMessage(Message message) {
    try {
      TextMessage textMsg = (TextMessage) message;
      System.out.println(textMsg.getText());
    } catch (JMSException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

}

If you followed the previous post you should see the “Seam ROCKS!” message.

That’s great but in the real world you will probably be working with objects and not simple text messages. Don’t worry. With Seam and EJB 3.0 this is also a breeze.

Lets assume in the previous post I sent a Person object to the queue instead of a text message. The code below shows you how to read the Person object from the queue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package osbi.achs.messaging;

import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.ejb.ActivationConfigProperty;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.log.Log;
import osbi.achs.model.Person;

@MessageDriven(name = "SearchQueueListenerBean", activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "/queue/achsSearch") })
public class SearchQueueListenerBean implements MessageListener {
  @Logger
  private Log log;

  @Override
  public void onMessage(Message message) {
   
    try {
      ObjectMessage objectMessage = (ObjectMessage)message;
      Person person = (Person) objectMessage.getObject();
      // TODO Do something with message
      System.out.println("Person = " + person.getSurName() + ", " + person.getGivenName());
    } catch (JMSException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

}

Messaging couldn’t be any easier.



JMS Messaging with Seam

Seam makes it easy to send and receive JMS messages to and from Seam components. In this post I am going to show you how to configure JBoss Messaging and Seam to send a message to a JMS Queue.

The first you need to do is configure JBoss to create the queue on startup. NOTE: Seam will not create the queue. If you forget to do this Seam will complain about not being able to bind to the queue.

  • Create an xml file in your JBoss AS deploy directory. I named mine ACHS-jms-destinations-service.xml.

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<server>
   <mbean code="org.jboss.jms.server.destination.QueueService"
     name="jboss.messaging.destination:service=Queue,name=achsSearch"
     xmbean-dd="xmdesc/Queue-xmbean.xml">
      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
      <depends>jboss.messaging:service=PostOffice</depends>
   </mbean>
</server>
  • Now start JBoss AS and check to see if your queue has been created. To check open up the JBoss Web Console(http://localhost:8080/web-console). Click on System -> JMX MBeans and scroll down to jboss.messaging.destination. You should see your newly created queue. In my example below it is named achsSearch.

screenhunter_05-2009-08-07

Now that we have our queue created we need to configure Seam to use the queue.

  • The following 2 lines need to be placed in the compenents.xml file.
  • The first line tells Seams where to find the queue and creates a Seam compenent called searchQueueSender. You can name this whatever you like.
  • The second line tells Seam to use the connection factor that supports JTA. This enables it to participate in transactions. Pretty sweet. The other connection factories (e.g. ConnectionFactory) only support local transactions.

1
2
3
<jms:managed-queue-sender name="searchQueueSender" auto-create="true" queue-jndi-name="/queue/achsSearch" />

<jms:queue-connection queue-connection-factory-jndi-name="java:/JmsXA" />

Believe it or not that is all of the configuration that is needed. Now to coding.

  • Below is an action class that simply submits a text message to the queue. The big gotcha I ran into here is that Seam also has a QueueSession library and Eclipse imported that one when I tried to fix the missing imports. I had to add the javax.jms libraries to my classpath before I could import the 2 correct javax.jms libraries needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//Package Statement

//Be sure and use the javax libraries and not Seam Queue libraries
import javax.jms.QueueSender;
import javax.jms.QueueSession;

//Other Import Statements

@Name("newSearch")
@Scope(ScopeType.CONVERSATION)
public class NewSearch {
  @In
  private QueueSender searchQueueSender;
  @In(create = true)
  private QueueSession queueSession;

  public void submitSearch() {
    try {
      //Send message to queue
      searchQueueSender.send(queueSession.createTextMessage("Seam ROCKS!"));
    } catch (Exception e) {
      log.error(e.getMessage());
    }
  }
}
  • To verify that your message arrived you can check the JBoss Web Console by clicking on your Queue and looking at the MessageCount field.


Believe or not that is it. I ran into a few gotchas but overall pretty easy and very cool. Seam makes JMS a breeze.



RichFaces Webinar Series

Recently Exadel had a 4 part webinar series on RichFaces. I attended most of them and thought they were pretty good. The series was pretty simple but did a good job highlighting RichFaces features. Definitely worth checking out.