Document Information

Preface

Part I Introduction

1.  Overview

2.  Using the Tutorial Examples

Part II The Web Tier

3.  Getting Started with Web Applications

4.  JavaServer Faces Technology

5.  Introduction to Facelets

6.  Expression Language

7.  Using JavaServer Faces Technology in Web Pages

8.  Using Converters, Listeners, and Validators

9.  Developing with JavaServer Faces Technology

10.  JavaServer Faces Technology: Advanced Concepts

11.  Using Ajax with JavaServer Faces Technology

12.  Composite Components: Advanced Topics and Example

13.  Creating Custom UI Components and Other Custom Objects

14.  Configuring JavaServer Faces Applications

15.  Java Servlet Technology

16.  Uploading Files with Java Servlet Technology

17.  Internationalizing and Localizing Web Applications

Part III Web Services

18.  Introduction to Web Services

19.  Building Web Services with JAX-WS

20.  Building RESTful Web Services with JAX-RS

21.  JAX-RS: Advanced Topics and Example

Part IV Enterprise Beans

22.  Enterprise Beans

23.  Getting Started with Enterprise Beans

24.  Running the Enterprise Bean Examples

25.  A Message-Driven Bean Example

26.  Using the Embedded Enterprise Bean Container

27.  Using Asynchronous Method Invocation in Session Beans

Part V Contexts and Dependency Injection for the Java EE Platform

28.  Introduction to Contexts and Dependency Injection for the Java EE Platform

29.  Running the Basic Contexts and Dependency Injection Examples

30.  Contexts and Dependency Injection for the Java EE Platform: Advanced Topics

31.  Running the Advanced Contexts and Dependency Injection Examples

Part VI Persistence

32.  Introduction to the Java Persistence API

33.  Running the Persistence Examples

34.  The Java Persistence Query Language

35.  Using the Criteria API to Create Queries

36.  Creating and Using String-Based Criteria Queries

37.  Controlling Concurrent Access to Entity Data with Locking

38.  Using a Second-Level Cache with Java Persistence API Applications

Part VII Security

39.  Introduction to Security in the Java EE Platform

40.  Getting Started Securing Web Applications

41.  Getting Started Securing Enterprise Applications

42.  Java EE Security: Advanced Topics

Part VIII Java EE Supporting Technologies

43.  Introduction to Java EE Supporting Technologies

44.  Transactions

45.  Resources and Resource Adapters

46.  The Resource Adapter Example

47.  Java Message Service Concepts

Overview of the JMS API

What Is Messaging?

What Is the JMS API?

When Can You Use the JMS API?

How Does the JMS API Work with the Java EE Platform?

Basic JMS API Concepts

JMS API Architecture

Messaging Domains

Point-to-Point Messaging Domain

Publish/Subscribe Messaging Domain

Programming with the Common Interfaces

Message Consumption

Creating Robust JMS Applications

Using Basic Reliability Mechanisms

Controlling Message Acknowledgment

Specifying Message Persistence

Setting Message Priority Levels

Allowing Messages to Expire

Creating Temporary Destinations

Using Advanced Reliability Mechanisms

Creating Durable Subscriptions

Using JMS API Local Transactions

Using the JMS API in Java EE Applications

Using @Resource Annotations in Enterprise Bean or Web Components

Using Session Beans to Produce and to Synchronously Receive Messages

Managing JMS Resources in Session Beans

Managing Transactions in Session Beans

Using Message-Driven Beans to Receive Messages Asynchronously

Managing Distributed Transactions

Using the JMS API with Application Clients and Web Components

Further Information about JMS

48.  Java Message Service Examples

49.  Bean Validation: Advanced Topics

50.  Using Java EE Interceptors

Part IX Case Studies

51.  Duke's Bookstore Case Study Example

52.  Duke's Tutoring Case Study Example

53.  Duke's Forest Case Study Example

Index

 

The JMS API Programming Model

The basic building blocks of a JMS application are:

  • Administered objects: connection factories and destinations

  • Connections

  • Sessions

  • Message producers

  • Message consumers

  • Messages

Figure 47-5 shows how all these objects fit together in a JMS client application.

Figure 47-5 The JMS API Programming Model

Diagram of the JMS API programming model: connection factory, connection, session, message producer, message consumer, messages, and destinations

This section describes all these objects briefly and provides sample commands and code snippets that show how to create and use the objects. The last subsection briefly describes JMS API exception handling.

Examples that show how to combine all these objects in applications appear in later sections. For more detail, see the JMS API documentation, part of the Java EE API documentation.

JMS Administered Objects

Two parts of a JMS application, destinations and connection factories, are best maintained administratively rather than programmatically. The technology underlying these objects is likely to be very different from one implementation of the JMS API to another. Therefore, the management of these objects belongs with other administrative tasks that vary from provider to provider.

JMS clients access these objects through interfaces that are portable, so a client application can run with little or no change on more than one implementation of the JMS API. Ordinarily, an administrator configures administered objects in a JNDI namespace, and JMS clients then access them by using resource injection.

With GlassFish Server, you can use the asadmin create-jms-resource command or the Administration Console to create JMS administered objects in the form of connector resources. You can also specify the resources in a file named glassfish-resources.xml that you can bundle with an application.

NetBeans IDE provides a wizard that allows you to create JMS resources for GlassFish Server. See To Create JMS Resources Using NetBeans IDE for details.

JMS Connection Factories

A connection factory is the object a client uses to create a connection to a provider. A connection factory encapsulates a set of connection configuration parameters that has been defined by an administrator. Each connection factory is an instance of the ConnectionFactory, QueueConnectionFactory, or TopicConnectionFactory interface. To learn how to create connection factories, see To Create JMS Resources Using NetBeans IDE.

At the beginning of a JMS client program, you usually inject a connection factory resource into a ConnectionFactory object. For example, the following code fragment specifies a resource whose JNDI name is jms/ConnectionFactory and assigns it to a ConnectionFactory object:

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

In a Java EE application, JMS administered objects are normally placed in the jms naming subcontext.

JMS Destinations

A destination is the object a client uses to specify the target of messages it produces and the source of messages it consumes. In the PTP messaging domain, destinations are called queues. In the pub/sub messaging domain, destinations are called topics. A JMS application can use multiple queues or topics (or both). To learn how to create destination resources, see To Create JMS Resources Using NetBeans IDE.

To create a destination using the GlassFish Server, you create a JMS destination resource that specifies a JNDI name for the destination.

In the GlassFish Server implementation of JMS, each destination resource refers to a physical destination. You can create a physical destination explicitly, but if you do not, the Application Server creates it when it is needed and deletes it when you delete the destination resource.

In addition to injecting a connection factory resource into a client program, you usually inject a destination resource. Unlike connection factories, destinations are specific to one domain or the other. To create an application that allows you to use the same code for both topics and queues, you assign the destination to a Destination object.

The following code specifies two resources, a queue and a topic. The resource names are mapped to destination resources created in the JNDI namespace.

@Resource(lookup = "jms/Queue")
private static Queue queue;

@Resource(lookup = "jms/Topic")
private static Topic topic;

With the common interfaces, you can mix or match connection factories and destinations. That is, in addition to using the ConnectionFactory interface, you can inject a QueueConnectionFactory resource and use it with a Topic, and you can inject a TopicConnectionFactory resource and use it with a Queue. The behavior of the application will depend on the kind of destination you use and not on the kind of connection factory you use.

JMS Connections

A connection encapsulates a virtual connection with a JMS provider. For example, a connection could represent an open TCP/IP socket between a client and a provider service daemon. You use a connection to create one or more sessions.


Note - In the Java EE platform, the ability to create multiple sessions from a single connection is limited to application clients. In web and enterprise bean components, a connection can create no more than one session.


Connections implement the Connection interface. When you have a ConnectionFactory object, you can use it to create a Connection:

Connection connection = connectionFactory.createConnection();

Before an application completes, you must close any connections you have created. Failure to close a connection can cause resources not to be released by the JMS provider. Closing a connection also closes its sessions and their message producers and message consumers.

connection.close();

Before your application can consume messages, you must call the connection’s start method; for details, see JMS Message Consumers. If you want to stop message delivery temporarily without closing the connection, you call the stop method.

JMS Sessions

A session is a single-threaded context for producing and consuming messages. You use sessions to create the following:

Sessions serialize the execution of message listeners; for details, see JMS Message Listeners.

A session provides a transactional context with which to group a set of sends and receives into an atomic unit of work. For details, see Using JMS API Local Transactions.

Sessions implement the Session interface. After you create a Connection object, you use it to create a Session:

Session session = connection.createSession(false,
     Session.AUTO_ACKNOWLEDGE);

The first argument means the session is not transacted; the second means the session automatically acknowledges messages when they have been received successfully. (For more information, see Controlling Message Acknowledgment.)

To create a transacted session, use the following code:

Session session = connection.createSession(true, 0);

Here, the first argument means the session is transacted; the second indicates that message acknowledgment is not specified for transacted sessions. For more information on transactions, see Using JMS API Local Transactions. For information about the way JMS transactions work in Java EE applications, see Using the JMS API in Java EE Applications.

JMS Message Producers

A message producer is an object that is created by a session and used for sending messages to a destination. It implements the MessageProducer interface.

You use a Session to create a MessageProducer for a destination. The following examples show that you can create a producer for a Destination object, a Queue object, or a Topic object.

MessageProducer producer = session.createProducer(dest);
MessageProducer producer = session.createProducer(queue);
MessageProducer producer = session.createProducer(topic);

You can create an unidentified producer by specifying null as the argument to createProducer. With an unidentified producer, you do not specify a destination until you send a message.

After you have created a message producer, you can use it to send messages by using the send method:

producer.send(message);

You must first create the messages; see JMS Messages.

If you have created an unidentified producer, use an overloaded send method that specifies the destination as the first parameter. For example:

MessageProducer anon_prod = session.createProducer(null);
anon_prod.send(dest, message);

JMS Message Consumers

A message consumer is an object that is created by a session and used for receiving messages sent to a destination. It implements the MessageConsumer interface.

A message consumer allows a JMS client to register interest in a destination with a JMS provider. The JMS provider manages the delivery of messages from a destination to the registered consumers of the destination.

For example, you could use a Session to create a MessageConsumer for a Destination object, a Queue object, or a Topic object:

MessageConsumer consumer = session.createConsumer(dest);
MessageConsumer consumer = session.createConsumer(queue);
MessageConsumer consumer = session.createConsumer(topic);

You use the Session.createDurableSubscriber method to create a durable topic subscriber. This method is valid only if you are using a topic. For details, see Creating Durable Subscriptions.

After you have created a message consumer it becomes active, and you can use it to receive messages. You can use the close method for a MessageConsumer to make the message consumer inactive. Message delivery does not begin until you start the connection you created by calling its start method. (Remember always to call the start method; forgetting to start the connection is one of the most common JMS programming errors.)

You use the receive method to consume a message synchronously. You can use this method at any time after you call the start method:

connection.start();
Message m = consumer.receive();
connection.start();
Message m = consumer.receive(1000); // time out after a second

To consume a message asynchronously, you use a message listener, as described in the next section.

JMS Message Listeners

A message listener is an object that acts as an asynchronous event handler for messages. This object implements the MessageListener interface, which contains one method, onMessage. In the onMessage method, you define the actions to be taken when a message arrives.

You register the message listener with a specific MessageConsumer by using the setMessageListener method. For example, if you define a class named Listener that implements the MessageListener interface, you can register the message listener as follows:

Listener myListener = new Listener();
consumer.setMessageListener(myListener);

Note - In the Java EE platform, a MessageListener can be used only in an application client, not in a web component or enterprise bean.


After you register the message listener, you call the start method on the Connection to begin message delivery. (If you call start before you register the message listener, you are likely to miss messages.)

When message delivery begins, the JMS provider automatically calls the message listener’s onMessage method whenever a message is delivered. The onMessage method takes one argument of type Message, which your implementation of the method can cast to any of the other message types (see Message Bodies).

A message listener is not specific to a particular destination type. The same listener can obtain messages from either a queue or a topic, depending on the type of destination for which the message consumer was created. A message listener does, however, usually expect a specific message type and format.

Your onMessage method should handle all exceptions. It must not throw checked exceptions, and throwing a RuntimeException is considered a programming error.

The session used to create the message consumer serializes the execution of all message listeners registered with the session. At any time, only one of the session’s message listeners is running.

In the Java EE platform, a message-driven bean is a special kind of message listener. For details, see Using Message-Driven Beans to Receive Messages Asynchronously.

JMS Message Selectors

If your messaging application needs to filter the messages it receives, you can use a JMS API message selector, which allows a message consumer to specify the messages that interest it. Message selectors assign the work of filtering messages to the JMS provider rather than to the application. For an example of an application that uses a message selector, see An Application That Uses the JMS API with a Session Bean.

A message selector is a String that contains an expression. The syntax of the expression is based on a subset of the SQL92 conditional expression syntax. The message selector in the example selects any message that has a NewsType property that is set to the value 'Sports' or 'Opinion':

NewsType = ’Sports’ OR NewsType = ’Opinion’

The createConsumer and createDurableSubscriber methods allow you to specify a message selector as an argument when you create a message consumer.

The message consumer then receives only messages whose headers and properties match the selector. (See Message Headers, and Message Properties.) A message selector cannot select messages on the basis of the content of the message body.

JMS Messages

The ultimate purpose of a JMS application is to produce and consume messages that can then be used by other software applications. JMS messages have a basic format that is simple but highly flexible, allowing you to create messages that match formats used by non-JMS applications on heterogeneous platforms.

A JMS message can have three parts: a header, properties, and a body. Only the header is required. The following sections describe these parts.

For complete documentation of message headers, properties, and bodies, see the documentation of the Message interface in the API documentation.

Message Headers

A JMS message header contains a number of predefined fields that contain values used by both clients and providers to identify and route messages. Table 47-1 lists the JMS message header fields and indicates how their values are set. For example, every message has a unique identifier, which is represented in the header field JMSMessageID. The value of another header field, JMSDestination, represents the queue or the topic to which the message is sent. Other fields include a timestamp and a priority level.

Each header field has associated setter and getter methods, which are documented in the description of the Message interface. Some header fields are intended to be set by a client, but many are set automatically by the send or the publish method, which overrides any client-set values.

Table 47-1 How JMS Message Header Field Values Are Set

Header Field

Set By

JMSDestination

send or publish method

JMSDeliveryMode

send or publish method

JMSExpiration

send or publish method

JMSPriority

send or publish method

JMSMessageID

send or publish method

JMSTimestamp

send or publish method

JMSCorrelationID

Client

JMSReplyTo

Client

JMSType

Client

JMSRedelivered

JMS provider

Message Properties

You can create and set properties for messages if you need values in addition to those provided by the header fields. You can use properties to provide compatibility with other messaging systems, or you can use them to create message selectors (see JMS Message Selectors). For an example of setting a property to be used as a message selector, see An Application That Uses the JMS API with a Session Bean.

The JMS API provides some predefined property names that a provider can support. The use of these predefined properties or of user-defined properties is optional.

Message Bodies

The JMS API defines five message body formats, also called message types, which allow you to send and receive data in many different forms and which provide compatibility with existing messaging formats. Table 47-2 describes these message types.

Table 47-2 JMS Message Types

Message Type

Body Contains

TextMessage

A java.lang.String object (for example, the contents of an XML file).

MapMessage

A set of name-value pairs, with names as String objects and values as primitive types in the Java programming language. The entries can be accessed sequentially by enumerator or randomly by name. The order of the entries is undefined.

BytesMessage

A stream of uninterpreted bytes. This message type is for literally encoding a body to match an existing message format.

StreamMessage

A stream of primitive values in the Java programming language, filled and read sequentially.

ObjectMessage

A Serializable object in the Java programming language.

Message

Nothing. Composed of header fields and properties only. This message type is useful when a message body is not required.

The JMS API provides methods for creating messages of each type and for filling in their contents. For example, to create and send a TextMessage, you might use the following statements:

TextMessage message = session.createTextMessage();
message.setText(msg_text);     // msg_text is a String
producer.send(message);

At the consuming end, a message arrives as a generic Message object and must be cast to the appropriate message type. You can use one or more getter methods to extract the message contents. The following code fragment uses the getText method:

Message m = consumer.receive();
if (m instanceof TextMessage) {
    TextMessage message = (TextMessage) m;
    System.out.println("Reading message: " + message.getText());
} else {
    // Handle error
}

JMS Queue Browsers

Messages sent to a queue remain in the queue until the message consumer for that queue consumes them. The JMS API provides a QueueBrowser object that allows you to browse the messages in the queue and display the header values for each message. To create a QueueBrowser object, use the Session.createBrowser method. For example:

QueueBrowser browser = session.createBrowser(queue);

See A Simple Example of Browsing Messages in a Queue for an example of using a QueueBrowser object.

The createBrowser method allows you to specify a message selector as a second argument when you create a QueueBrowser. For information on message selectors, see JMS Message Selectors.

The JMS API provides no mechanism for browsing a topic. Messages usually disappear from a topic as soon as they appear: If there are no message consumers to consume them, the JMS provider removes them. Although durable subscriptions allow messages to remain on a topic while the message consumer is not active, no facility exists for examining them.

JMS Exception Handling

The root class for exceptions thrown by JMS API methods is JMSException. Catching JMSException provides a generic way of handling all exceptions related to the JMS API.

The JMSException class includes the following subclasses, described in the API documentation:

  • IllegalStateException

  • InvalidClientIDException

  • InvalidDestinationException

  • InvalidSelectorException

  • JMSSecurityException

  • MessageEOFException

  • MessageFormatException

  • MessageNotReadableException

  • MessageNotWriteableException

  • ResourceAllocationException

  • TransactionInProgressException

  • TransactionRolledBackException

All the examples in the tutorial catch and handle JMSException when it is appropriate to do so.