Tuesday Jun 25, 2013

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

"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:

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();
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      MessageProducer messageProducer = session.createProducer(demoQueue);
      TextMessage textMessage = session.createTextMessage(payload);
    } catch (JMSException ex) {
    } finally {
      if (connection != null) {
        try {
        } catch (JMSException ex) {

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:

public class SimplifiedMessageSender {

  JMSContext context;

  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
    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 ? 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:


Wednesday Dec 26, 2012

Simple JMS 2.0 Sample - @JMSDestinationDefinition and Synchronous Message Receive: TOTD #191

JMS 2.0 Early Draft - Simplified API Sample Code explained some of the changes that are made in JMS 2.0 to "catch up" with all the changes in the Java SE and EE platform over the past few years. The main goals of JMS 2.0 are:
  • Changes to improve ease-of-development
  • Clarification of relationship between JMS and other Java EE specifications
  • Definition of a new mandatory API to allow any JMS provider to be integrated with any other Java EE Application Server
  • Other enhancements as requested by the community
This Tip Of The Day (TOTD) will explain a simple sample showing how to send a message and receive it synchronously. The complete source code for the sample can be downloaded here.

This is a Stateless EJB that has a single method to send a message.

public class MessageSender {

JMSContext context;

Queue queue;

public void sendMessage(String message) {
context.createProducer().send(queue, message);
In this code:
  • JMSContext is a new interface introduced in the simplified API in JMS 2.0. This combines in a single object the functionality of two separate objects from the JMS 1.1 API: a Connection and a Session.

    A JMSContext may be injected in the Java EE web and EJB containers using the @Inject annotation. A JMSContext created in this way is described as being container-managed. A container-managed JMSContext will be closed automatically by the container. Applications running in the Java EE web and EJB containers are not permitted to create more than one active session on a connection. This allows to combine them in a single object offering a simpler API. This is the recommended way for creating JMS context in Java EE applications.

    A JMSContext may be created by calling one of the createContext methods on a ConnectionFactory. A JMSContext that is created this way is described as being application-managed. An application-managed JMSContext must be closed when no longer needed by calling its close method. Applications running in a Java SE environment or in the Java EE application client container are permitted to create multiple active sessions on the same connection. This allows the same physical connection to be used in multiple threads simultaneously. The createContext method is recommended to create JMSContext in such applications.
  • The Java EE Platform requires a preconfigured JMS ConnectionFactory accessible to the application under the JNDI name:
    The annotation @JMSConnectionFactory may be used to specify the JNDI lookup name of the ConnectionFactory used to create the JMSContext as:
    JMSContext context;
    If no lookup name is specified or the @JMSConnectionFactory is omitted then the platform default JMS connection factory will be used. The above code fragment is equivalent to:
    JMSContext context;
  • @Resource defines a dependency on a resource needed by the application. In this case, it specifies the JNDI name of the destination to which the message needs to be sent.
  • When an application needs to send messages it uses the createProducer method to create JMSProducer which provides methods to configure and send messages. The various setProperty methods are used to set property on the message being sent. There are several other methods like setPriority, setDeliveryDelay, and setTimeToLive to set other quality-of-service attributes for the message being sent.

    Messages may be sent synchronously or asynchronously. Synchronous messages are sent using one of the send methods. Asynchronous messages are sent using setAsync method and assigning a CompletionListener. When the message has been successfully sent the JMS provider invokes the callback method onCompletion on the CompletionListener object. If the message is not sent for some reason or an acknowledgement from the remote JMS server is not received then onException callback method is called. An asynchronous send is not permitted in a Java EE application.

This is a Stateless EJB that has a single method to receive the message synchronously.

public class MessageReceiverSync {

private JMSContext context;

Queue myQueue;

public String receiveMessage() {
String message = context.createConsumer(myQueue).receiveBody(String.class, 1000);
return "Received " + message;

In this code:
  • JMSContext referring to the preconfigured JMS ConnectionFactory is injected by the container.
  • @Resource defines a dependency on the JMS destination on which the message is received.
  • When an application needs to receive messages it uses one of the several createConsumer or createDurableConsumer methods to create a JMSConsumer. createConsumer creates a non-durable subscription on the specified destination. This means that a client will only see the messages published on the destination when the subscriber is active. If the subscriber is not active, it is missing messages published on the destination. createDurableConsumer creates an unshared durable subscription of a specified topic and creates a consumer on that subscription. This allows the subscriber will receive all messages published on a topic, including the ones published when there is no active consumer associated with it. The JMS provider retains a record of this durable subscription and ensures that all messages from the topic's publishers are retained until they are delivered to, and acknowledged by, a consumer on this durable subscription or until they have expired.

    A JMSConsumer provides methods to receive messages either synchronously or asynchronously. receive methods are used for synchronous delivery of the messages. A MessageListener object may be registered with the client for asynchronous delivery of the messages. onMessage method of the MessageListener object are called as messages are received. Asynchronous delivery of messages will not work until MQ-264 is fixed.
Next is a Servlet that ties all the pieces together. It defines the JMS Destination and send and receive the message using the previously defined EJBs.

@JMSDestinationDefinition(name = "java:global/jms/myQueue",
resourceAdapterName = "jmsra",
className = "javax.jms.Queue",
description="My Queue")
@WebServlet(urlPatterns = {"/TestServlet"})
public class TestServlet extends HttpServlet {

@EJB MessageSender sender;

@EJB MessageReceiverSync receiver;

void doGet(HttpServletRequest request, HttpServletResponse response) {
. . .
String m = "Hello there";
out.format("Message sent: %1$s.<br>", m);
out.println("Receiving message...<br>");
String message = receiver.receiveMessage();
out.println("Message received: " + message);
. . .
In this code:
  • @JMSDestinationDefinition defines the JMS destination. The name attribute defines the JNDI name of the destination being defined, destinationName attribute defines the name of the queue or topic, and className attribute defines the JMS destination implementation class name.
  • doGet method uses the injected EJBs to send and receive the message.
The complete source code for the sample can be downloaded here. "mvn package" and deploy the generated WAR file.

Download GlassFish 4 build 68 onwards and try this sample today!

The latest progress on JMS 2.0 can be tracked at:

Help us make JMS 2.0 better, simpler, easier to use. Join users@jms-spec and contribute!


profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.

Java EE 7 Samples

Stay Connected


« March 2015