Seam extends the CDI programming model into the messaging world by allowing you to inject JMS resources into your beans. Further, Seam bridges the CDI event bus over JMS; this gives you the benefits of CDI-style type-safety for inter-application communication.
The JMS module for Seam 3 is to provide injection of JMS resources and the necessary scaffolding for a bidirectional propagation of CDI event over JMS.
The general goals can be divided into two categories: injection of JMS resources and bridging of events:
JMS Resource Injection
Event Bridge
Seam JMS can be used by including a few libraries in your application's library folder:
If you are using Maven as your build tool use the following dependency:
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>seam-jms</artifactId>
<version>${seam.jms.version}</version>
</dependency>
Define or replace the property ${seam.jms.version} with a valid version of Seam JMS.
In this chapter we'll look at how to inject some of the common JMS resource types.
The following JMS resources are now available for injection:
Destination-based resources:
The injection of resources that are themselves a javax.jms.Destination or require one needs
a hint: What destination do you want to work with? This is provided by the
@JmsDestination annotatation.
@Inject @JmsDestination(jndiName="jms/MyTopic") Topic t; @Inject @JmsDestination(jndiName="jms/MyQueue") Queue q;
You should create your own qualifier to provide type safe injection of predefined destinations:
@Qualifier
@JmsDestination(jndiName = "jms/MyTopic")
public @interface MyTopic {}
You can then use it in place of the @JmsDestination qualifier anywhere it's required:
@Inject @MyTopic TopicPublisher myPub; ... @Inject @MyTopic Topic myTopic;
You can use the @JmsSession qualifier when injecting javax.jms.Session to specify transacted and acknowledgement type:
@Inject @JmsSession(transacted=true, acknowledgementType=Session.CLIENT_ACKNOWLEDGE) Session s;
TODO Add other configuration options as they are implemented.
This chapter is designed to detail how to configure the CDI to JMS event bridge. Routing has two sides, sending of events to JMS destinations and translating received messages from JMS destinations back into CDI events. The sections of this chapter will describe how to achieve both.
The act of simply sending a message to a JMS destination involves a few players: Connection, Session, Destination, and the message itself. Surely you can inject all required resources and perform the forwarding yourself but that takes away from the whole reason you're using a tool in the first place! Let's let a little configuration do the work for us.
Introducing the JmsForwarding interface:
@Named
@ApplicationScoped
public interface JmsForwarding
{
public Set<? extends Destination> getDestinations();
public Type getEventType();
public Set<Annotation> getQualifiers();
}
The JmsForwarding interface allows for simple mapping of event types, complete with
qualifiers, to a set of destinations. Every bean found implementing JmsForwarding will be
used to create a bridge from CDI to the JMS world, forwarding all events that match the event type and
qualifiers returned.
JmsForwarding.getQualifiers() should only return annotations that are in fact
qualifiers. If not, Seam JMS will detect the problem and treat it as a deployment problem.
Since your JmsForwarding objects are CDI Beans you can use dependency injection to
obtain the destinations you wish to forward to.
With your configuration bean defined you can simply fire events that match a configuration's event type and qualifiers and these events will be forwarded over JMS as object messages.
@Inject @Bridged Event<MyObject> event; ... event.fire(myObject);
Here's a sample configuration that will match any MyObject event fired with the
qualifier @Bridged:
@Named
@ApplicationScoped
public class MyForwarding implements JmsForwarding
{
@Inject @MyTopic private Topic t;
public Set<? extends Destination> getDestinations()
{
return Collections.singleton(t);
}
public Type getEventType()
{
return MyObject.class;
}
public Set<Annotation> getQualifiers()
{
return Collections.<Annotation> singleton(new AnnotationLiteral<Bridged>(){});
}
}
And here's an event that will be sent to JMS due to the configuration above:
@Inject @Bridged Event<MyObject> event; ... event.fire(myObject);
TODO Reference to example showing this off