X

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



"What's New in JMS 2.0" href="http://www.oracle.com/technetwork/articles/java/jms20-1947669.html">Part
1 and href="http://www.oracle.com/technetwork/articles/java/jms2messaging-1954190.html">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 href="http://vshow.on24.com/vshow/oraclejava#exhibits/java">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.
  • All APIs throw checked exceptions 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. This of course
    works only in Java EE Web or EJB applications and does not apply
    in Java SE-based applications where injection is not available.

  • 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.

  • Creating JMSConsumer also starts the connection so there is no
    need to explicitly start it.

  • JMSContext, Session, Connection,
    JMSProducer and JMSConsumer objects
    are now AutoCloseable. This means that these
    resources are closed automatically by the management of
    try-with-resources statement.

  • New simplified API throws a new unchecked exception,
    JMSRuntimeException. This means try/catch blocks are not
    required.

  • 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 ? href="//cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/f4a5b21d-66fa-4885-92bf-c4e81c06d916/File/5370f59e6d925b57505aaf5a62833804/totd213_jms2_launch_demo.zip">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!


Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services