Message Driven POJOs by Mark Fisher
Last night, I attended the New England Java Users Group to see Mark Fisher talk about Message Driven POJOs. This was the first JUG I've been to (outside of Denver's) where I was an attendee instead of a speaker. It was interesting to see how they do things. They have one main speaker who speaks for two hours. After the first hour, they have a break, offer pizza and do a raffle. Then the speaker continues. They require you to "register" at least 48 hours before the meeting starts. This is because the meeting is held at Sun and they (apparently) need to do it for security purposes. They actually checked my ID and made sure I was registered at the door. After I passed their verification test, I received a name tag. While I like Denver's Basic Concepts followed by Main Speaker setup, I liked that this JUG meeting was over at 8:15. Below are my notes from the event.
Topics in this Session: Overview of JMS, Spring's JmsTemplate and implementing a Message Driven POJO.
Goals of JMS: provide a vendor-neutral abstraction for accessing Message Oriented Middleware from Java. It provides for enterprise messaging systems what JDBC provides for relational databases. See Wikipedia's definition of JMS for more information.
The API is what insulates your code from the JMS implementation you're using. The JMS implementation will use a message broker to communicate between servers. Tonight, Mark will be using ActiveMQ in his examples. He plans on doing most of his presentation in Eclipse because he's been spending 14 hours per day in PowerPoint revamping Interface21's training courses (I don't miss that at all).
The JMS Message is the central object to JMS. There's various types of messages, TextMessage, ObjectMessage (I missed the rest). Two types of JMS Destinations are available: Queues and Topics. A JMS Session is used to create messages as well as producers and consumers. Examples calls:
session.createTextMessage(String)
session.createConsumer(dest)
session.createProducter(dest)
A JMS Connection is obtained from a JMS ConnectionFactory. The ConnectionFactory is typically accessed by a JNDI Lookup.
JMS is most commonly used for internal application communications (not public facing).
Templates are common in the Spring Framework and are used to simply API usage. Their main goal is to reduce boilerplate code (resource management, try/catch, etc.). Examples include JdbcTemplate, JpaTemplate, JndiTemplate, TransactionTemplate and (you guessed it) JmsTemplate. Spring also translates exceptions to consistent runtime hierarchies. In addition to one-line methods, Spring's templates supply callbacks that alleviate try/catch blocks - but give you full power of the API.
JmsTemplate has a couple of capabilities: it handles acquisition and release of resources and translates checked JMS Exceptions to a parallel hierarchy of RuntimeExceptions. It's also capable of converting a payload to the corresponding JMS message type with a MessageConverter strategy. Lastly, it provides convenience methods to allow sending asynchronous messages.
Now Mark is showing us how you configure a ConnectionFactory, Queue and JmsTemplate in a Spring context file. The first couple of beans only take 3 lines of code to configure, the 3rd one takes 4 because it has a dependency on the first two. Pretty easy configuration if you ask me. After composing bean definitions, Mark created a JUnit test and called jmsTemplate.convertAndSend()
to send a message in 2 lines of Java code.
To receive messages with JmsTemplate (pre Spring 2.0), you could use synchronous receive calls: receive()
, receive(Destination)
and receive(String)
. There are also receiveAndConvert()
methods.
In Spring 2.0, they added the ability to do MessageListener containers to enable asynchronous reception in a non application server environment. Implementations include SimpleMessageListenerContainer, DefaultMessageListenerContainer and ServerSessionMessageListenerContainer. The DMLC adds transactional behavior, and the SSMLC hooks into the server's SPI. Spring's MessageListenerAdapter enables the delegation to a POJO for handling the payload.
For the next 1/2 hour or so, Mark wrote a bunch of Java and XML to create a simple Trader application. About the same time, I got managed to get an internet connection from somewhere and started browsing the net and answering e-mail. Every once in a while I looked up to see Mark's code - it all looks very simple and straight forward. In Spring 2.1, a <jms:*> namespace will be added to simplify the XML configuration.
For those of you out there using Spring's JMS support - are there any issues you've run into? Are you using it in production? It's always pimped as "awesome", so I'm looking for pain points that folks might encounter when using it.
Related: Spring's JMS Documentation and ActiveMQ's JmsTemplate Gotchas.
ServerSessionMessageListenerContainer not working could be an ActiveMQ 3.x issue though.. I haven't tried it with ActiveMQ 4.x
I've been using this in production for a while and haven't had issues with the Sping JMS classes.
Posted by Sanjiv Jivan on February 23, 2007 at 08:21 PM MST #
Actually I had no issues with both(even with over a million messages a day) but I was using Weblogic JMS Server instead of ActiveMQ.
The only difference I noticed, as usual with Spring, I was more productive and it was so easy when when had to move the JMS Server around (changing IP addresses).
JMS is the way to go when in your workflow you have a change to use a asynchronous processing.
Posted by Alexandre Jacques on February 23, 2007 at 10:23 PM MST #
JMSTemplate, however, should be avoided in my experience. It is better in 2.0, but it still doesn't cut it. It is overly complicated and doesn't work when you want to do anything fancy (more often than you think).
If you really want to do something fun, use JavaSpaces instead of JMS - there is a Spring module for it if you want.
Mike
Posted by Mike Herrick on February 24, 2007 at 05:40 AM MST #
When you are ready for some real P/C action look here: http://www.cs.wustl.edu/~schmidt/ACE-overview.html.
Posted by Alonso on February 24, 2007 at 05:48 AM MST #
Posted by Jason on February 28, 2007 at 05:16 AM MST #
Posted by Gabriel on March 01, 2007 at 09:44 PM MST #