Show TOC Start of Content Area

Background documentation JMS Overview  Locate the document in its SAP Library structure

Use

The Java Message Service (JMS) is an enterprise messaging system that provides a way for business applications to exchange data without needing to be directly connected to each other. The communication is obtained using messages.

Note that JMS is not a product itself, but a set of predefined interfaces provided in the javax.jms package. The applications use this API to send and receive messages to and from a destination located on the JMS Provider. Java programs that send and/or receive messages using JMS are called JMS clients.

The Java applications can use JMS to send and receive messages using an enterprise messaging server in a standardized, vendor-independent way. The actual messaging product that implements the JMS interfaces is the JMS Provider.

The AS Java contains a JMS 1.1 compliant JMS Provider.

JMS Objects Hierarchy

Some of these objects are administered objects according to the JMS specification. These objects are created and configured using an administration tool.

This graphic is explained in the accompanying text

Connection Factory

An administrated object you use to create JMS connections. Connection factories are obtained (looked up) from the JNDI.

Connection

The connection is a factory for session objects.

Session

A single-threaded context for sending and receiving messages. Using the session you can create a:

      Message producer

An object created by the session used to send messages to a destination.

      Message consumer

An object created by the session used to receive messages sent to a destination.

      Message

The messages are the actual information exchanged by JMS clients.

Destinations

The destination is an administered object that implements the abstraction of a message destination. The destination messaging model could be:

      Point-to-point (queue destination)

Use it to send messages that only one specified consumer can receive, that is, “one-to-one” message delivery.

This graphic is explained in the accompanying text

This model allows you to send messages to a queue. The message producer here is called the sender. The messages remain in the queue until they are consumed and acknowledged by a consumer, called the receiver. At that time, these messages are deleted from the queue. The SAP JMS Provider guarantees only that each message is delivered to exactly one receiver; it does not specify if and how multiple receivers on a single queue should be handled.

 Caution

The behavior of the SAP JMS Provider for multiple receivers on a queue is configurable. There are two possible configurations: exclusive (multiple receivers are not allowed. An attempt to register a second receiver results in an exception) and round-robin (multiple receivers are allowed and served in a round-robin fashion, which is the default one). The round-robin policy feature can be used for load balancing your applications, for example; multiple instances of your receiver program can connect themselves to a queue and receive incoming messages in a round-robin fashion. However, applications that rely on this behavior are not necessarily portable across different JMS Providers.

A special type of a queue receiver is the queue browser. It retrieves messages from a queue without deleting them. This enables programs such as monitoring tools to inspect the contents of a queue without actually consuming its messages.

      Publish-subscribe (topic destination)

Use it to send messages to a group of consumers, that is, “one-to-many” message delivery. The model also allows you to create durable subscribers, which enable you to get a message sent to this destination while the consumer was not active.

This graphic is explained in the accompanying text

This model allows you to send these messages to a topic. An arbitrary number of JMS clients can subscribe to a topic and receive a copy of all messages sent to that topic. Here the message producers are called publishers, while the message consumers are called subscribers.

Destination objects are set up as administered objects and then retrieved by the JMS client at runtime using JNDI instead of being directly instantiated. The JMS specification also offers you the option to dynamically instantiate temporary destinations.

JMS Programming Model

The basic steps you have to take to create a new JMS connection are:

...

       1.      Obtain the server’s initial JNDI context.

       2.      Look up a connection factory.

You need the connection factory to create JMS connections.

       3.      Create a JMS connection.

It encapsulates the idea of an abstract connection between s JMS Client and a message server. It is also a factory for JMS sessions.

       4.      Create a JMS session.

The JMS session is required to create message producers, message consumers and JMS messages.

       5.      Look up the destination.

The destination is the place where the messages will be sent to or read from.

       6.      Start the connection.

This activates your JMS connection. Before the connection is started, no messages can be received from it.

       7.      Create a message producer and/or consumer.

       8.      Close the connection.

This releases JMS objects that are not required once you have finished using them in the application.

Step 1: Obtain a connection factory via lookup or injection

a. Via lookup
Obtain the initial context

Specify the connection and the security properties required to obtain the initial JNDI context.

java.util.Properties properties = new Properties();

 

// set the properties of the connection

properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sap.engine.services.jndi.InitialContextFactoryImpl");

properties.put(Context.PROVIDER_URL, "localhost:50004");

properties.put(Context.SECURITY_PRINCIPAL, "Administrator");

properties.put(Context SECURITY_CREDENTIALS, "administrator_access_password ");

 

// start the initial context with the specified properties

InitialContext context = new InitialContext(properties);

The properties that have to be set may differ depending on the client type. For example, internal clients of the server (in other words, deployed on it) do not need to specify any properties, while external (remote) clients have to specify additional properties.

Look up a connection factory

The JMS Provider has predefined the following (default) connection factories:

      ConnectionFactory

A generic factory, introduced in JMS 1.1 as part of the domain unification. Enables you to create generic connections that can work with both queues and topics.

      TopicConnectionFactory

Enables you to create topic connections.

      QueueConnectionFactory

Enables you to create queue connection.

      XAConnectionFactory

A generic factory for XA transaction-enabled connections. Introduced in JMS 1.1 as part of the domain unification. Enables you to create generic XA-enabled connections that can work with both queues and topics.

      XATopicConnectionFactory

Enables you to create XA transaction-enabled topic connections.

      XAQueueConnectionFactory

Enables you to create XA transaction-enabled queue connections.

To perform a lookup operation, you also need a resource reference entry for the relevant administered object in the deployment descriptor of the component that looks up the object:

      Declare a JMS connection factory in the <res-ref-name> element of the standard deployment descriptor for the relevant application component. The name that you specify in the <res-ref-name>tag is the name used for the lookup operation.

 Note

To register a connection factory, use the JMS Connector service.

      Declare a JMS Destination resource in the <res-env-ref-name> element of the standard deployment descriptor of the application component. The name that you specify in the <res-env-ref-name> tag is the name used for the lookup operation.

To look up a connection factory, use the following code:

ConnectonFactory ConnectionFactory = (ConnectionFactory)

context.lookup("java:comp/env/<res-ref-name>");

b. Via injection

To inject the JMS connection factories, use the @Resource annotation.

More information: Accessing JMS Resources

Step 3: Create a connection

Using the connection factory object, create the connection object:

// create connection

Connection connection = connectionFactory.createConnection();

If you want to provide a user name and password, use the following code:

// create connection

Connection connection = connectionFactory.createConnection(user, password);

Note

If you do not authenticate creating the connection, all subsequent JMS operations through this connection are done on behalf of the current thread’s user. In the second case all operations are done on behalf of the specified user.

Step 4: Create a session

Using the connection object, create a session object, providing the necessary session parameters:

// create session

Session Session = connection.createSession(false/true,

Session.AUTO_ACKNOWLEDGE/Session.CLIENT_ACKNOWLEDGE/

Session.DUPS_OK_ACKNOWLEDGE);

The first parameter shows if the session is transacted. The second parameter specifies the acknowledgement mode.

 Note

The session cannot be accessed concurrently from different threads according to the JMS specification. If you are coding a multithreaded application, you have to create and use a separate session object for each thread.

Step 5: Obtain, look up or inject a destination

Since destinations are administered objects, they must be created either using an administrative tool, or they can be defined in the jms-resources.xml descriptor of your application and deployed as part of it. Note that the createQueue() and createTopic() methods of the session, despite their names, are not required by the specification to physically create a destination, they just fetch an already existing one. SAP JMS Provider implementation of these methods physically creates the destination, if it does not exist. We recommend that you do not rely on this functionality because it is completely vendor-specific and, therefore, not portable. Another disadvantage is that programmatically created JMS destinations can only be removed manually, via the SAP NetWeaver Administrator. They will not be removed automatically if the application is undeployed.

...

      To create a destination, use the following code:

// retrieve an existing destination of type topic

Topic topic = session.createTopic("Example_topic_name");

      To look up a destination, for example a queue, use the following code:

Queue queue = (Queue) context.lookup("java:comp/env/<res-env-ref-name>");

      To inject a destination, use the following code:

@Resource(name = "jms/MyQueue")

private Queue queue;

More information: Accessing JMS Resources

In some scenarios you can choose to create and use temporary destinations.

You create these destinations dynamically and they last as long as the lifetime of the connection. You can create consumers of temporary destinations only from the same connection that created the destination.

The temporary destinations:

      Are intended to facilitate a simple request/reply mechanism.

      Represent a message queue or topic to which a producer can send and from which a consumer can receive messages.

      Exist only for the lifetime of the connection in which they are created.

      Are deleted when the connection is closed, and all messages inside the destination are lost.

      Are not intended to survive a server failure.

      Only consumers created in the same connection as the temporary destination can receive messages from it, although all producers can send messages to it.

Note

We recommend using temporary destinations whenever your application design allows it. Creating and removing temporary destinations is more efficient and requires less resources than nontemporary destinations.

To create a temporary destination, use the following source code:

// create a new temporary queue

Queue queue = session.createTemporaryQueue();

// create a new temporary topic

Topic topic = session.createTemporaryTopic();

Step 6: Create a message producer or consumer

To create a message producer on a topic, use the following code:

// create a topic publisher

TopicPublisher topicPublisher = session.createPublisher(topic);

To create a message producer on a queue, use the following code:

// create a queue receiver

QueueReceiver queueReceiver = session.createReciver(queue);

Note

Messages must not be accessed concurrently from different threads according to the JMS specification.

More information: Creating Message Producers and Consumers

Step 7: Send or receive messages

You can use the message producer and/or consumer you have created in the previous step.

To send a text message to a topic, use the following code:

message = topicSession.createTextMessage();

topicPublisher.send(message);

To receive a text message from a queue, use the following code:

textMessage = (TextMessage)queueReceiver.receive();

textMessage.getText();

Step 8: Close the connection

When you have finished using the JMS connection, close all producers, consumers, sessions and the connection itself. This releases the resources that have been allocated for these objects on the server.

If you are using a point-to-point model, use the following code to close the connection object:

// Close the queue connection

queueConnection.close();

If you are using a publish-subscribe model, use the following code to close the connection object:

// Close the topic connection

topicConnection.close();

JMS Messages

A JMS message consists of three parts:

...

       1.      Header

                            a.      System properties

Used to identify and route the JMS message. The header of a message consists of the following fields:

       JMSDestination

The destination the message is sent to.

       JMSDeliveryMode

Defines the delivery mode for the message.

       JMSMessageID

A unique identifier for this message.

       JMSTimestamp

The timestamp when the message was sent.

       JMSCorrelationID

Shows whether the message is linked to another message.

       JMSReplyTo

The destination the message reply should be sent to.

       JMSRedelivered

If this field is set to true, this means that the message has been delivered in the past. That means that the application has to take extra precautions to prevent duplicate processing.

       JMSType

The message type identifier.

       JMSExpiration

Contains the value that shows the expiration time of the message.

       JMSPriority

Shows the priority of the message. Allowed values are: integers between 0 and 9, 0 is highest priority.

                            b.      Custom Properties

Used optionally to define application-specific key-value pairs.

       2.      Body

The message payload.

Message Types

There are several message types defined by the JMS specification that the applications can create and receive, all implementing the javax.jms.Message interface.

      Generic Message

A message with no payload, consisting only of a message header and properties. It is also the base class of all the other message types. Use the Message type when you do not need to send any message content (for example, when you need just a property value, or for some event notification).

      Bytes Messages

This type of messages represents an array of bytes. You can use this message type for exchanging data in some native format between applications or for sending binary data, such as image files.

      Map Messages

The message has a body containing a set of name-value pairs. In this pair, the names are Strings and the values are typed. These entries can be accessed in random order by name or by enumeration. There is no order of the entries. Use the MapMessage type to send data that can be organized into name/value pairs.

      Object Messages

An object message has a payload that is a Serializable Java object. Use the ObjectMessage type to send a serialized Java object from one application component to another.

Note

The receiving application must have the class of the object in its classpath.

      Stream Messages

A stream message contains a stream of Java primitive values. This message data is read in sequence.

      Text Messages

A message that contains java.lang.String object. Use the TextMessage type to send traditional text, HTML, or XML messages.

Message Acknowledgement

When you create a new session, you specify the acknowledgement type. The JMS specification allows the messages to be acknowledged both implicitly and explicitly. The acknowledgement depends on the type of the session.

If the session is not transacted, there are a few types of acknowledgement:

      DUPS_OK_ACKNOWLEDGE – this acknowledgment mode instructs the session to lazily acknowledge the delivery of messages. This is likely to result in the delivery of duplicate messages if the JMS Provider crashes, so it should only be used by consumers that can tolerate duplicate messages. Use of this mode can reduce session overheads by minimizing the work the session does to prevent duplicates.

      AUTO_ACKNOWLEDGE – this enables automatic session acknowledgement when the client receives messages, if the message receipt was successful or if the MessageListener called by the message returns successfully.

      CLIENT_ACKNOWLEDGE – with this acknowledgement mode, the client acknowledges a consumed message by calling the message's acknowledge method. Acknowledging a consumed message acknowledges all messages that the session has consumed. When client acknowledgment mode is used, a client may build up a large number of unacknowledged messages while attempting to process them.

Applications that use the automated modes AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE do not have control over the acknowledgement mechanism, and therefore do not know whether the consumer has already acknowledged the receipt of a particular message. This becomes an issue if a Provider error occurs just before or during message acknowledgement. For example, in which case the JMS Provider is unable to determine whether the consumer did not receive the message itself or if just the acknowledgement was lost. As a result, the provider will resend the last message sent (with the mode AUTO_ACKNOWLEDGE) or all messages sent since the last successful acknowledgement (with the mode DUPS_OK_ACKNOWLEDGE).

More information: Processing Messages

Deployment of JMS Resources

Using the JMS Provider, you can create, remove or update JMS resources. You can define a JMS resources deployment descriptor (jms-resources.xml) and package it with your application.

The XML also provides options for creating non-SAP resource references.

Here is the description of deployment of SAP JMS Resources:

      Deploy application of JMS Resources

When an application containing a JMS resource descriptor is deployed, the respective JMS resources are automatically created if they do not already exist. If they do already exist (for example they could have been deployed by another application or they could have been administratively created), they are just associated with the application. The JMS resources can be deployed either as standalone (becoming global, that is, available to all applications), or as part of the resources of an application (becoming local for this application). Local JMS resources are available only to the application that deploys them. It is also possible to share a JMS resource between two or more applications: all applications define the respective resource with one and the same name, the resource is created during the deployment of the first application and then associated with the rest of the applications upon their deployment. Such resources are called “shared”.

      Update application with JMS Resources

When an application containing a JMS resource descriptor is redeployed, the set of JMS resources defined in the descriptor is matched against the set of existing JMS resources. In case a resource does not exist, it is created; in case it exists and it is not shared, its properties are updated with the properties supplied in the descriptor (if any) and finally, in case there are resources that exist for this application but are no longer present in the descriptor, they are removed (unless these resources are global or shared). The last deployed resource can change the properties. We recommend that you make sure you are the only one who uses these resources; to do that you have to make them local. In this way, there are no collisions with the global resources. The redeployment of JMS resources is also called update of JMS resources.

      Remove application with JMS Resources

When an application containing a JMS resource descriptor is undeployed, the respective JMS resources are automatically removed, unless they are global or shared. This is true only for <sap-local-factory-type>.

For <sap-local-factory-type> the jms-resources schema provides the opportunity not only to create JMS resources, but also to configure them by optionally providing custom values for some of their properties.

More information: Creating and Configuring JMS Resources and Resource References

End of Content Area