21.2. Messaging in Seam

It is easy to send and receive JMS messages to and from Seam components.

21.2.1. Configuration

To configure Seam infrastructure to send JMS messages, you must first tell Seam about the topics and queues you want to send messages to, and where to find the QueueConnectionFactory and TopicConnectionFactory, depending on your requirements.
By default, Seam uses UIL2ConnectionFactory, the default connection factory with JBossMQ. If you use another JMS provider, you must set one or both of queueConnection.queueConnectionFactoryJndiName and topicConnection.topicConnectionFactoryJndiName, in either seam.properties, web.xml, or components.xml.
To install Seam-managed TopicPublishers and QueueSenders, you must also list topics and queues in components.xml:
<jms:managed-topic-publisher name="stockTickerPublisher" 
     auto-create="true" topic-jndi-name="topic/stockTickerTopic"/> 
    
<jms:managed-queue-sender name="paymentQueueSender" 
     auto-create="true" queue-jndi-name="queue/paymentQueue"/>

21.2.2. Sending messages

Once configuration is complete, you can inject a JMS TopicPublisher and TopicSession into any component:
@Name("stockPriceChangeNotifier")
public class StockPriceChangeNotifier {
  @In private TopicPublisher stockTickerPublisher;   

  @In private TopicSession topicSession;

  public void publish(StockPrice price) {
    try {
      stockTickerPublisher.publish(topicSession
                                   .createObjectMessage(price));
    } catch (Exception ex) {
      throw new RuntimeException(ex);
    } 
  }
}
Or, to work with a queue:
@Name("paymentDispatcher")
public class PaymentDispatcher {
  @In private QueueSender paymentQueueSender;   
    
  @In private QueueSession queueSession;
    
  public void publish(Payment payment) {
    try {
      paymentQueueSender.send(queueSession.createObjectMessage(payment));
    } catch (Exception ex) {
      throw new RuntimeException(ex);
    } 
  }
}

21.2.3. Receiving messages using a message-driven bean

You can process messages with any EJB3 message-driven bean. Message-driven beans can sometimes be Seam components, in which case, you can inject other event- and application-scoped Seam components. The following is an example of the payment receiver, which delegates to the payment processor.

Note

You may need to set the create attribute on the @In annotation to true so that Seam can create an instance of the component to be injected. (This is necessary only if the component does not support auto-creation — that is, it is not annotated with @Autocreate.)
First, create a message-driven bean to receive the message:
@MessageDriven(activationConfig = 
    {@ActivationConfigProperty(propertyName = "destinationType",
                               propertyValue = "javax.jms.Queue"),
     @ActivationConfigProperty(propertyName = "destination",
                               propertyValue = "queue/paymentQueue")
})

@Name("paymentReceiver")
public class PaymentReceiver implements MessageListener
{
  @Logger private Log log;

  @In(create = true) private PaymentProcessor paymentProcessor;
    
  @Override
  public void onMessage(Message message)
  {
    try {
      paymentProcessor.processPayment((Payment) ((ObjectMessage) 
                                      message).getObject());
    } catch (JMSException ex) {
      log.error("Message payload did not contain a Payment object", ex);
    } 
  }
}
Next, implement the Seam component to which the receiver will delegate payment processing:
@Name("paymentProcessor")
public class PaymentProcessor {
  @In private EntityManager entityManager;

  public void processPayment(Payment payment) {
    // perhaps do something more fancy
    entityManager.persist(payment);
  }
}
If you want to perform transaction operations in your message-driven bean, ensure that you are working with an XA datasource, or you will not be able to roll back database changes in the event that a database transaction commits, but a subsequent message operation fails.

21.2.4. Receiving messages in the client

Seam Remoting lets you subscribe to a JMS topic from client-side JavaScript. You can find more information in Chapter 24, Remoting.