Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Make the Right Decision with Our Side-by-Side Comparison of Spring and EJB 3.0, Part 2


advertisement
his is the second article in a two-part series comparing Spring and EJB 3.0. The first article looked at how each technology addresses persistence, transaction management, and state. In this article I'll continue the analysis by looking into other characteristics such as messaging, remoting, dependency management, and intermediation, and I'll conclude by offering an overall analysis of the two technologies and several integration strategies for combining the best of both.

Messaging
Enterprise applications often don't exist in isolation but must interact with other applications and services running within and outside a company. Messaging is a common approach to this problem and support is provided by both Spring and EJB 3.0. There are two basic operations in messaging: sending and receiving. And, typically, there are two methods of receiving messages: explicit message retrieval and automatic notification (listening).

MessagingFunctional Comparison
To explore how Spring and EJB 3.0 each implement the sending of Java Message Service (JMS) messages, consider the sequence of steps I've outlined for the purchasing of an airline ticket (see Figure 1).

A Spring implementation of the TsaScreener object is shown below:

<code> public class TsaPassengerScreenerClientSpring implements TsaPassengerScreener { private JmsTemplate jmsTemplate; private Queue queue; public void screenPassenger(final Passenger passenger) { jmsTemplate.send(queue, new MessageCreator() { public Message createMessage(Session session) throws JMSException { return session.createObjectMessage(passenger); } }); } ... } </code>
The necessary configuration to support this implementation is shown below:
<code> <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate" /> <bean id="tsaQueue" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiTemplate"> <ref bean="jndiTemplate" /> </property> <property name="jndiName"> <value>java:comp/env/queue/tsaQueue</value> </property> </bean> <bean id="tsaQCF" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiTemplate"> <ref bean="jndiTemplate" /> </property> <property name="jndiName"> <value>java:comp/env/queue/tsaQCF</value> </property> </bean> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <constructor-arg> <ref bean="tsaQCF" /> </constructor-arg> </bean> <bean id="tsaPassengerScreener" class="org.jug.flight.booking.spring.TsaPassengerScreenerClientSpring"> <property name="jmsTemplate" ref="jmsTemplate" /> <property name="tsaQueue" ref="tsaQCF" /> </bean> </code>
Compare this to the EJB 3.0 implementation:
<code> @Stateless public class TsaPassengerScreenerClientEJB implements TsaPassengerScreener { @Resource(mappedName = "java:/ConnectionFactory") QueueConnectionFactory factory; @Resource(mappedName = "queue/tsaQueue") Queue queue; public void screenPassenger(Passenger passenger) { try { QueueConnection con = factory.createQueueConnection(); QueueSession session = con.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE); ObjectMessage msg = session.createObjectMessage(passenger); QueueSender sender = session.createSender(queue); sender.send(msg); session.close(); con.close(); } catch (Exception e) { e.printStackTrace(); } } } </code>
Figure 1. Purchase Ticket Sequence Diagram. In this example the purchase ticket use case has been expanded to send a message to the TSA with the details of the passenger who is booking a flight.

Notice that the Spring implementation uses the JmsTemplate helper class to simplify working with the JMS API to send the message. Also, notice that in both cases the container injects the JMS resources (queue connection factory and queue) into the screener object. I'll explore injection more later, in the section on dependency management. But at this point it is interesting to note the Spring configuration is more verbose then the EJB equivalent.

After the passenger details message has been sent the TSA needs to receive and process it. Both Spring and EJB 3.0 can support notification of objects when incoming messages arrive. These objects are referred to as message listeners. A Spring implementation of a message-driven POJO (MDP) is shown below:

<code> public class TsaPassengerScreenerMDP implements MessageListener { public void onMessage(Message message) { ObjectMessage objectMessage = (ObjectMessage) message; try { Passenger passenger = (Passenger) objectMessage.getObject(); // Process message } catch (JMSException e) { e.printStackTrace(); } } } </code>
The necessary configuration to support this implementation is shown below:
<code> <bean id="tsaListener" class="org.jug.flight.booking.spring.TsaPassengerScreenerMDP" /> <bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="concurrentConsumers" value="5" /> <property name="connectionFactory" ref="tsaQCF" /> <property name="destination" ref="tsaQueue" /> <property name="messageListener" ref="tsaListener" /> </bean> </code>
Compare this to the EJB 3.0 implementation of a message-driven bean (MDB):
<code> @MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/tsaQueue") }) public class TsaPassengerScreenerMDB implements MessageListener { public void onMessage(Message message) { ObjectMessage objectMessage = (ObjectMessage) message; try { Passenger passenger = (Passenger) objectMessage.getObject(); // Process message } catch (JMSException e) { e.printStackTrace(); } } } </code>
As shown above, both Spring and EJB 3.0 enable the sending and receiving of JMS messages. And interestingly the implementations of message consumption via a Spring MDP and an EJB MDB are quite similar. Additionally, both solutions allow the volume of concurrent message processing to be throttled allowing you to tune the amount of resources allocated within an application to message processing. In the case of EJBs this is a container-specific function whereas with Spring it is a function of the message listener container.

Another important feature of enterprise messaging solutions is their ability to participate in distributed transactions. Often multiple resources will be involved in message processing (typically messaging and database resources) and the work performed on these resources should be performed atomically. Both Spring and EJB 3.0 allow messaging activities to participate in distributed transactions. In EJB 3.0 however, in order to have message acknowledgement tied to successful completion of a transaction, you will need to use container-managed transactions, otherwise messages that have been previously processed may be redelivered. The same can be accomplished in Spring when using JTA transactions and when the message container is defined as "sessionTransacted." In either case you could choose to allow message redelivery and handle this case programmatically.

A more telling difference in messaging support between Spring and EJB is the type of objects that can be configured to listen for incoming messages. In EJB message listeners must be EJB components whereas in Spring any POJO can potentially be activated in response to incoming messages. Both require that the message listener implement an interface and both support the javax.jms.MessageListener interface for JMS message listeners. However, since the 2.1 version of the EJB specification EJB MDBs can support other messaging interfaces such as javax.resource.cci.MessageListener which allow MDBs to be activated by a JCA CCI connector.

MessagingNon-Functional Comparison
Most Java applications use JMS to interact with an underlying message provider. This is the case with both Spring and EJB 3.0. But Spring provides templates that assist with retrieving the necessary message resources from the application server (via JNDI) and for creating, sending, and receiving messages. EJB 3.0 allows message resources to be injected into a class via its dependency injection facilities, but it does not provide any facility equivalent to Spring's template to simplify the use of the JMS API. Spring also provides message converters which can automate the conversion of Java objects to message content.

In terms of standardization both approaches support the Java standard for messaging, JMS. In terms of implementation however MDBs are a JCP standard whereas Spring MDPs are not. But although MDPs are not a standard they are portable as the Spring runtime can run in any JSE or JEE container.

MessagingSummary
Table 1 summarizes the key differences between Spring and EJB 3.0s messaging support. Table 1. Messaging Features in Spring and EJB 3.0.

Feature Spring EJB 3.0
Message Listening
Listener Types Any POJOimplementing the javax.jms.MessageListener interface MDBs implementing any interface appropriate to its messaging type, usually javax.jms.MessageListener
Message Throttling (Container specific)
Messaging Support (Templates, Message Converters) -- (No support above the JMS API)
Distributed Transaction Support


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.