X

JMS 2.0 Early Draft - Simplified API Sample Code

Guest Author


Java Message Service (JSR
343
) is undergoing a major revision as part of Java EE 7. The
href="http://jcp.org/aboutJava/communityprocess/edr/jsr343/index.html">Early
Draft of the specification has been available for a few weeks
now and href="http://jms-spec.java.net/2.0-SNAPSHOT/apidocs/index.html">online
javadocs are now available. Several other specifications such
as href="http://jcp.org/aboutJava/communityprocess/edr/jsr338/index.html">JPA
2.1, href="http://jcp.org/aboutJava/communityprocess/edr/jsr339/index.html">JAX-RS
2.0, href="http://jcp.org/aboutJava/communityprocess/edr/jsr345/index.html">EJB
3.2, href="http://jcp.org/aboutJava/communityprocess/edr/jsr344/">JavaServer
Faces 2, and href="http://jcp.org/aboutJava/communityprocess/edr/jsr346/index.html">CDI
1.1 in the Java EE 7 umbrella have released early drafts. Some
of the specs have been explained in detailed:
  • href="https://blogs.oracle.com/arungupta/entry/jax_rs_2_0_early">JAX-RS
    2.0 Early Draft Explained
  • href="http://blogs.oracle.com/arungupta/entry/jpa_2_1_early_draft">JPA
    2.1 Early Draft Explained
  • What's new in JSF 2.2
    ?
    (external contribution)


This blog will provide an update on href="http://jcp.org/aboutJava/communityprocess/edr/jsr343/index.html">JMS
2.0 Early Draft.



JMS 1.1 was released in href="http://www.jcp.org/en/jsr/detail?id=914">Dec 2003. A lot
has chnged in the Java landscape since then - think about
annotations, generics, auto-closeable, dependency injection, and a
lot more. The Java EE platform itself has evolved extensively since
then, especially Java EE 6 is a "game changer". There are multiple
JMS implementations still running solid and so there is lot of
development/deployment experience on that as well. Keeping all of
that, and much more, in mind, the main goals of JMS 2.0 are:
  • Changes to improve ease of development
  • Clarification of relationship between the JMS and other Java
    EE specifications
  • Definition of a new mandatory API to allow any JMS provider to
    be integrated with any Java EE application server
  • Extensions to support Java EE 7
  • Other enhancements as requested by the community


This blog will take a code sample from the section 11.4 of the href="http://jcp.org/aboutJava/communityprocess/edr/jsr343/index.html">Early
Draft to highlight how ease-of-development changes are now
coming to JMS 2.0.



This is how a message is sent using the existing JMS API:


@Resource(lookup = "jms/connectionFactory ")
ConnectionFactory connectionFactory;
@Resource(lookup="jms/inboundQueue")
Queue inboundQueue;
public void sendMessageOld (String payload) {
Connection connection = null;
try {
connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(inboundQueue);
TextMessage textMessage = session.createTextMessage(payload);
messageProducer.send(textMessage);
} catch (JMSException e) {
// do something
} finally {
try {
if (connection != null)
connection.close();
} catch (JMSException e2) {
// do something else
}
}
}

This works very well but several issues with it:

  1. Multiple intermediate objects such as Connection,
    Session, and MessageProducer need to
    be created in order to send a message. All these objects serve a
    purpose but makes the JMS application more complicated. It also
    leads to lots of boilerplate code as well.

  2. The arguments to createSession are confusing.
    The first argument specifies whether the session is transacted
    or not. The second argument specifies, how, if you used the
    session to receive messages, how those messages would be
    acknowledged. These two arguments are not independent. If the
    first argument is set to true then the second argument is
    irrelevant. So we only need one argument here.



    The other part is when this method is in a EJB then the
    transactions are controlled by the container. Or if a
    bean-managed transactions are used then the transaction would be
    started and committed using the UserTransaction
    API, not by methods in the JMS API. In fact, the EJB spec says
    that if this code is running in a transaction then the arguments
    to createSession are completely ignored. And even
    then we are required to supply some arguments here to satisfy
    the contract.
  3. The Connection need to explicitly closed in the
    finally block in order to release the resources appropriately on
    the server side. The code does not even show closing of MessageProducer
    and Session and And the finally block gets ugly
    with nested exceptions.

Now lets take a look at how the new API will simplify the
programming model:


@Resource(lookup = "jms/connectionFactory")
ConnectionFactory connectionFactory;

@Resource(lookup="jms/inboundQueue")
Queue inboundQueue;

public void sendMessageNew (String payload) {
try (JMSContext context = connectionFactory.createContext();){
context.send(inboundQueue,payload);
}
}

Simple, isn't it ?



Here are the main changes:

  1. All the boilerplate is gone. Instead just create a ConnectionFactory,
    create a context from it, and invoke send on it.
  2. The destinatation (inboundQueue) is now specified on send
    insead of MessageProducer.
  3. Connection is now auto-closeable so try block
    will close it autoamatically.
  4. New methods throw runtime exception so the code looks much
    cleaner.

And if you are using Dependency Injection, then the code can be
further simplified to:

@Inject
@JMSConnectionFactory("jms/connectionFactory")
private JMSContext context;

@Resource(mappedName = "jms/inboundQueue")
private Queue inboundQueue;

public void sendMessageNew(String payload) {
context.send(inboundQueue, payload);
}

Some clean ups to note here are ...
  • No need for application to instantiate JMSContext
  • The same injected JMSContext is available in
    other places, if within the same CDI scope


How cool is that ?



Here is yet another example on how the simplified API receives a
message synchronously:


@Inject
@JMSConnectionFactory("jms/connectionFactory")
private JMSContext context;

@Resource(lookup="jms/inboundQueue")
Queue inboundQueue;

public String receiveMessageNew() {
JMSConsumer consumer = context.createConsumer(inboundQueue);
return consumer.receivePayload(String.class);
}



The section 11.4 of the JMS 2.0 Early Draft provide more lot more
samples with the standard (or existing) API and the simplified (or
new) API.



Do you like the direction that the JMS 2.0 Expert Group is taking ?
Would you like to provide feedback and contribute ?



The latest progress on JMS 2.0 can be tracked at:
  • jms-spec.java.net
  • JSR 343 EG archive at href="http://java.net/projects/jms-spec/lists/jsr343-experts/archive">jsr343-experts
  • Discussion at href="http://java.net/projects/jms-spec/lists/users/archive">users@jms-spec
  • JSR 343
    • href="http://jcp.org/aboutJava/communityprocess/edr/jsr343/index.html">Early
      Draft
    • Latest Javadocs (href="http://java.net/projects/jms-spec/sources/repository/content/jms2.0/target/jms-2.0-javadoc.jar">download,
      href="http://jms-spec.java.net/2.0-SNAPSHOT/apidocs/index.html">online)

Help us make JMS 2.0 better, simpler, easier to use. Join href="http://java.net/projects/jms-spec/lists/users/archive">users@jms-spec
and contribute!


Join the discussion

Comments ( 6 )
  • Rahi Akela Saturday, April 21, 2012

    This is a great change into Java Messaging Technology.I am so impressed........


  • Kamal Govindraj Sunday, April 22, 2012

    Looks good, better late than never.

    I was able to do something similar with the spring jmsTemplate (http://bit.ly/9MfgnA) since 2007.


  • Ramandeep Nanda Monday, April 23, 2012

    Great use of Java 7 features and the code is terse and also the code is easier to understand and maintain.


  • guest Tuesday, July 10, 2012

    I'm quite happy to see that CDI comes into play wit JMS. However, it would be an error not to know how to get rid of the default proposed behaviour. Great illusion would be to think of JMS as simply put a message on Queue/Topic and trust the defaults. A real messaging base in a business context is often pondered of custom needs defined in the software architecture/strategy: durability, availability, filters, ...

    As always, CDI can be considered here quite welcome, but it won't be in most cases accepted in terms of default behaviour.


  • guestRichard Sherman Thursday, December 27, 2012

    My nvidia hardware and software, which I wanted to update, came back with the message that they required the latest version of Java, and sent me to this website. I see nothing at this website which allows me to download the latest version of Java. I'm not interested in an "early draft". You geeks will never learn to communicate with ordinary people. How do I get "the latest version of Java?"


  • Arun Gupta Thursday, December 27, 2012

    The latest version of Java can be downloaded from:

    http://www.oracle.com/technetwork/java/javase/downloads/index.html


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