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 is a Stateless EJB that has a single method to send a message.
@StatelessIn this code:
public class MessageSender {
@Inject
JMSContext context;
@Resource(mappedName="java:global/jms/myQueue")
Queue queue;
public void sendMessage(String message) {
context.createProducer().send(queue, message);
}
}
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: aConnection
and aSession
.
AJMSContext
may be injected in the Java EE web and EJB containers using the@Inject
annotation. AJMSContext
created in this way is described as being container-managed. A container-managedJMSContext
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.
AJMSContext
may be created by calling one of thecreateContext
methods on aConnectionFactory
. AJMSContext
that is created this way is described as being application-managed. An application-managedJMSContext
must be closed when no longer needed by calling itsclose
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. ThecreateContext
method is recommended to createJMSContext
in such applications.- The Java EE Platform requires a preconfigured JMS
ConnectionFactory
accessible to the application under the JNDI name:java:comp/DefaultJMSConnectionFactory
The annotation@JMSConnectionFactory
may be used to specify the JNDI lookup name of theConnectionFactory
used to create the JMSContext as:@Inject
If no lookup name is specified or the
@JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory")
JMSContext context;@JMSConnectionFactory
is omitted then the platform default JMS connection factory will be used. The above code fragment is equivalent to:@Inject 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 createJMSProducer
which provides methods to configure and send messages. The varioussetProperty
methods are used to set property on the message being sent. There are several other methods likesetPriority
,setDeliveryDelay
, andsetTimeToLive
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 thesend
methods. Asynchronous messages are sent usingsetAsync
method and assigning aCompletionListener
. When the message has been successfully sent the JMS provider invokes the callback methodonCompletion
on theCompletionListener
object. If the message is not sent for some reason or an acknowledgement from the remote JMS server is not received thenonException
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.
@Stateless
public class MessageReceiverSync {
@Inject
private JMSContext context;
@Resource(mappedName="java:global/jms/myQueue")
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 JMSConnectionFactory
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
orcreateDurableConsumer
methods to create aJMSConsumer
.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.
AJMSConsumer
provides methods to receive messages either synchronously or asynchronously.receive
methods are used for synchronous delivery of the messages. AMessageListener
object may be registered with the client for asynchronous delivery of the messages.onMessage
method of theMessageListener
object are called as messages are received. Asynchronous delivery of messages will not work untilMQ-264 is fixed.
@JMSDestinationDefinition(name = "java:global/jms/myQueue",In this code:
resourceAdapterName = "jmsra",
className = "javax.jms.Queue",
destinationName="queue1234",
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";
sender.sendMessage(m);
out.format("Message sent: %1$s.<br>", m);
out.println("Receiving message...<br>");
String message = receiver.receiveMessage();
out.println("Message received: " + message);
. . .
}
- @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, andclassName
attribute defines the JMS destination implementation class name. doGet
method uses the injected EJBs to send and receive the message.
Download GlassFish 4 build 68 onwards and try this sample today!
The latest progress on JMS 2.0 can be tracked at:
- jms-spec.java.net
- JSR 343 EG archive at jsr343-experts
- Discussion at users@jms-spec
- JSR 343
- Latest
Specification
- Latest Javadocs (download,online)
Help us make JMS 2.0 better, simpler, easier to use. Join users@jms-spec
and contribute!