SeamFramework.orgCommunity Documentation
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 describe how to achieve both.
Simply sending or receiving a message over JMS involves a few players: Connection, Session, Destination, and the message itself. Surely you can inject all required resources and perform the routing yourself but that takes away from the whole reason you're using a tool in the first place!
Routing CDI events to and from JMS can be configured by defining a
Route
. As you would
normally create an observer method for an event you can define a route to control which events get
forwarded to what destination. Or conversely, what message types sent to which destinations generate CDI
events.
public interface Route { public <D extends Destination> Route connectTo(Class<D> d, D destination); public Route addQualifiers(Annotation... qualifiers); ... }
Routes allows for simple mapping of event types, complete with qualifiers, to a set of destinations. They
can be configured by adding qualifiers and providing destinations they should interact with and are created
from a
RouteManager
. Here's a simple route that forwards CDI events on to a queue:
@EventRouting public Route registerMyRoute(RouteManager routeManager) { Queue myQueue = lookupQueue("/jms/MyQueue"); return routeManager.createRoute(RouteType.EGRESS, MyEvent.class).connectTo(Queue.class, myQueue); }
A RouteManager
is a factory object for creating new Routes. An instance of it is injected
into every @EventRouting
method. Classes with methods that are decorated with EventRouting
must meet a few criteria items:
A default, no arg constructor.
Be a non bean (no dependencies on injection)
Return either Route
instances or Collection<Route>
instances.
These requirements exist because of when the generation of Route
s must happen.
There are no CDI beans active within the context. A class identified for routing will automatically
be veto'd from the context.
Routes are registered by returning them from a non-bean method annotated with
@EventRouting
:
@EventRouting public Route myConfig() { return bridge.createRoute(RouteType.INGRESS, MyEvent.class).addDestinationJndiName("/jms/MyTopic"); }
Forwarding CDI events to JMS is configured by creating an egress route. Let's say you wanted to forward all
MyEvent
events with
@Bridged
qualifier to the queue
jms/EventQueue
. Simple, register a route:
AnnotationLiteral<Bridged> BRIDGED = new AnnotationLiteral<Bridged>() {}; @EventRouting public Route registerMyEventRoute(RouteManager routeManager) { return routeManager.createRoute(RouteType.EGRESS, MyEvent.class).addQualifiers(BRIDGED).addDestinationJndiName("/jms/EventQueue"); }
With your routing defined you can simply fire events that match the route's payload type and
qualifiers and these events will be forwarded over JMS as object messages. A special note,
we have added the qualifier
@Routing(RouteType.EGRESS)
. This is necessary
to avoid circular routings.
@Inject @Bridged @Routing(RouteType.EGRESS) Event<MyEvent> event; ... event.fire(myEvent);
Similar to egress routes, ingress routes are defined the same way. In this case, they listen for messages on the specified destination(s) and fire events. All of the data will be type safe, assuming you have defined your routes correctly.
Similar to the above example, this creates ingress routes from the Queue jms/EventQueue and fires events based on the MyEvent objects that are carried over the wire.
AnnotationLiteral<Bridged> BRIDGED = new AnnotationLiteral<Bridged>() {}; @EventRouting public Route registerMyEventRoute(RouteManager routeManager) { return routeManager.createRoute(RouteType.INGRESS, MyEvent.class).addQualifiers(BRIDGED).addDestinationJndiName("/jms/EventQueue"); }
Once you define an ingress route, you handle it using an observer method. We use the same payload type
and qualifiers, however we need to add the same qualifier, but for ingress
@Routing(RouteType.INGRESS)
public void handleInboundMyEvent(@Observes @Routing(RouteType.INGRESS) MyEvent e) { .... }