JMSContext, @JMSDestinationDefintion, DefaultJMSConnectionFactory with simplified JMS API: TOTD #213

Posted by arungupta on Oracle Blogs See other posts from Oracle Blogs or by arungupta
Published on Tue, 25 Jun 2013 18:17:06 +0000 Indexed on 2013/06/25 22:25 UTC
Read the original article Hit count: 412

Filed under:

"What's New in JMS 2.0" Part 1 and Part 2 provide comprehensive introduction to new messaging features introduced in JMS 2.0. The biggest improvement in JMS 2.0 is introduction of the "new simplified API". This was explained in the Java EE 7 Launch Technical Keynote. You can watch a complete replay here.

Sending and Receiving a JMS message using JMS 1.1 requires lot of boilerplate code, primarily because the API was designed 10+ years ago. Here is a code that shows how to send a message using JMS 1.1 API:

@Stateless
public class ClassicMessageSender {

@Resource(lookup = "java:comp/DefaultJMSConnectionFactory")
ConnectionFactory connectionFactory;

@Resource(mappedName = "java:global/jms/myQueue")
Queue demoQueue;

public void sendMessage(String payload) {
Connection connection = null;
try {
connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(demoQueue);
TextMessage textMessage = session.createTextMessage(payload);
messageProducer.send(textMessage);
} catch (JMSException ex) {
ex.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException ex) {
ex.printStackTrace();
}
}
}
}
}

There are several issues with this code:
  • A JMS ConnectionFactory needs to be created in a application server-specific way before this application can run.
  • Application-specific destination needs to be created in an application server-specific way before this application can run.
  • Several intermediate objects need to be created to honor the JMS 1.1 API, e.g. ConnectionFactory -> Connection -> Session -> MessageProducer -> TextMessage.
  • Everything is a checked exception and so try/catch block must be specified.
  • Connection need to be explicitly started and closed, and that bloats even the finally block.
The new JMS 2.0 simplified API code looks like:

@Stateless
public class SimplifiedMessageSender {

@Inject
JMSContext context;

@Resource(mappedName="java:global/jms/myQueue")
Queue myQueue;

public void sendMessage(String message) {
context.createProducer().send(myQueue, message);
}
}

The code is significantly improved from the previous version in the following ways:
  • The JMSContext interface combines in a single object the functionality of both the Connection and the Session in the earlier JMS APIs.  You can obtain a JMSContext object by simply injecting it with the @Inject annotation. 
  • No need to explicitly specify a ConnectionFactory. A default ConnectionFactory under the JNDI name of
    java:comp/DefaultJMSConnectionFactory
    is used if no explicit ConnectionFactory is specified.
  • The destination can be easily created using newly introduced @JMSDestinationDefinition as:
    @JMSDestinationDefinition(name = "java:global/jms/myQueue",
            interfaceName = "javax.jms.Queue")

    It can be specified on any Java EE component and the destination is created during deployment.
  • JMSContext, Session, Connection, JMSProducer and JMSConsumer objects are now AutoCloseable. This means that these resources are automatically closed when they go out of scope. This also obviates the need to explicitly start the connection
  • JMSException is now a runtime exception.
  • Method chaining on JMSProducers allows to use builder patterns.
  • No need to create separate Message object, you can specify the message body as an argument to the send() method instead.

Want to try this code ? Download source code!

Download Java EE 7 SDK and install.
Start GlassFish: bin/asadmin start-domain
Build the WAR (in the unzipped source code directory): mvn package
Deploy the WAR: bin/asadmin deploy <source-code>/jms/target/jms-1.0-SNAPSHOT.war

And access the application at http://localhost:8080/jms-1.0-SNAPSHOT/index.jsp to send and receive a message using classic and simplified API.

A replay of JMS 2.0 session from Java EE 7 Launch Webinar provides complete details on what's new in this specification:



Enjoy!

© Oracle Blogs or respective owner

Related posts about /General