//enterprise java /
Lightweight Publish-Subscribe
Communication
Java EE 6 and CDI can be used for lean, efficient implementation of local publish-subscribe communication.
ADAM BIEN
JAVA IN ACTION
The ancient—in internet ime—J2EE specification
used Java Message Service (JMS)
as a workaround for asynchronous invocation of synchronous
services as well as for the distribution of local events. JMS,
unchanged in Java EE 6, has a
verbose API.
With Contexts and Dependency
Injection (CDI) 1.0 (JSR-299) and
Enterprise JavaBeans (EJB) 3. 1
(JSR-318), the J2EE workarounds
and patterns aren’t necessary.
JMS is still essential for true
messaging, but it is no longer
required for the implementation of asynchronous processing
or the implementation of a local
Observer pattern.
2.x components to be “legally”
invoked asynchronously. Service
Activator can be considered a
decorator that adds asynchronous nature as a cross-cutting
concern to an already existing
EJB interface.
The decoration usually comprised a JMS queue with a javax
.jms.MessageProducer as sender
and a message-driven bean as
an asynchronous receiver. Even
a Java EE 6 implementation of
Service Activator is not lean. You
need to implement a transactional message sender, which
uses a
javax.jms.Queue and a
javax.jms.ConnectionFactory, to
create and send a
javax.jms.Message
instance. Java EE
6 helps you only
by the acquisition
of the resources
with Dependency
Injection (JSR-330).
The major parts of
the code in Listing 1,
which shows
javax.jms.MessageProducer
wrapped with an EJB 3. 1 bean,
were generated with NetBeans 7
(using Alt+Insert on a Microsoft
Windows system or Ctrl+I on a
Mac system). However, the generated source code for the whole
lifecycle of the project must be
maintained.
A message-driven bean on the
other end of the queue receives
the message, casts it to a javax
.jms. TextMessage, extracts its payload, and passes it to the synchronous service. Listing 2 shows the
asynchronous receiver.
The message-driven bean in
Listing 2 is used only for asynchro-
nous invocation of
the synchronous
EJB bean. None
of the JMS fea-
tures or qualities
are used. We are
interested only in a
nonblocking invo-
cation by a thread
from the applica-
tion server’s pool.
Listing 3 shows the actual busi-
ness logic. After the injection of
the SynchronousService EJB 3. 1
bean into ServiceActivator, the
method message(String message)
is decorated with the asynchro-
nous onMessage method in the
message-driven bean.
Note: The implementation
described here is already simpli-
fied. In the original J2EE imple-
mentation, Dependency Injection
wasn’t available, so EJB 2 compo-
nents also required the use of Java
Naming and Directory Interface
(JNDI) lookups to get access to
other components. The imple-
mentation of the local EJBHome
and local interfaces, as well as the
existence of standard and propri-
etary XML deployment descrip-
tors, was also necessary. Service
Activator was a complex solution
to a trivial challenge.
ABOUT US
PHOTOGRAPH BY
THOMAS EINBERGER/
GETTY IMAGES
Asynchronous Invocation
As described in the “Context”
section of the Service Activator
pattern, “Enterprise beans and
other business services need a
way to be activated asynchronously.” The Service Activator
pattern was the only way for EJB
The main goals of
JMS 2.0 will be
simplicity and tight
integration with the
Java EE 7 specifications,
especially with CDI.
blog
The Java EE 6 Answer
Java EE 6 made the implementation of the Service Activator pattern obsolete. Listing 4 shows the