JavaTM Message Service Tutorial
Tutorial Homepage | TOC | Prev | Next | Index

A    JMS Client Examples

This appendix contains a number of sample programs that illustrate JMS API concepts and features. The samples are as follows:

The programs are all self-contained threaded applications. The programs include producer and consumer classes that send and receive messages. If you downloaded the tutorial examples as described in the preface, you will find the examples for this chapter in the directory jms_tutorial/examples/appendix (on UNIX® systems) or jms_tutorial\examples\appendix (on Microsoft Windows systems). You can compile and run the examples using the instructions in Chapter 4.

A.1   Durable Subscriptions

The DurableSubscriberExample.java program shows how durable subscriptions work. It demonstrates that a durable subscription is active even when the subscriber is not active. The program contains a DurableSubscriber class, a MultiplePublisher class, a main method, and a method that instantiates the classes and calls their methods in sequence.

The program begins like any publish/subscribe program: The subscriber starts, the publisher publishes some messages, and the subscriber receives them. At this point, the subscriber closes itself. The publisher then publishes some messages while the subscriber is not active. The subscriber then restarts and receives the messages.

Before you run this program, create a connection factory with a client ID. You can use a command similar to the one shown in Section 8.2.3, "Creating a Connection Factory." Then specify the connection factory name and the topic name on the command line when you run the program, as in the following sample command, for a Microsoft Windows system:

java -Djms.properties=%J2EE_HOME%\config\jms_client.properties DurableSubscriberExample DurableTopicCF jms/Topic

The output looks something like this:

Connection factory name is DurableTopicCF
Topic name is jms/Topic
Java(TM) Message Service 1.0.2 Reference Implementation (build b14)
Starting subscriber
PUBLISHER: Publishing message: Here is a message 1
PUBLISHER: Publishing message: Here is a message 2
PUBLISHER: Publishing message: Here is a message 3
SUBSCRIBER: Reading message: Here is a message 1
SUBSCRIBER: Reading message: Here is a message 2
SUBSCRIBER: Reading message: Here is a message 3
Closing subscriber
PUBLISHER: Publishing message: Here is a message 4
PUBLISHER: Publishing message: Here is a message 5
PUBLISHER: Publishing message: Here is a message 6
Starting subscriber
SUBSCRIBER: Reading message: Here is a message 4
SUBSCRIBER: Reading message: Here is a message 5
SUBSCRIBER: Reading message: Here is a message 6
Closing subscriber
Unsubscribing from durable subscription

A.2   Transactions

The TransactedExample.java program demonstrates the use of transactions in a JMS client application. The program represents a highly simplified e-Commerce application, in which the following things happen.

  1. A retailer sends a message to the vendor order queue, ordering a quantity of computers, and waits for the vendor's reply.
  2. The vendor receives the retailer's order message and places an order message into each of its suppliers' order queues, all in one transaction. This JMS transaction combines one synchronous receive with multiple sends.
  3. One supplier receives the order from its order queue, checks its inventory, and sends the items ordered to the destination named in the order message's JMSReplyTo field. If it does not have enough in stock, the supplier sends what it has. The synchronous receive and the send take place in one JMS transaction.
  4. The other supplier receives the order from its order queue, checks its inventory, and sends the items ordered to the destination named in the order message's JMSReplyTo field. If it does not have enough in stock, the supplier sends what it has. The synchronous receive and the send take place in one JMS transaction.
  5. The vendor receives the replies from the suppliers from its confirmation queue and updates the state of the order. Messages are processed by an asynchronous message listener; this step illustrates using JMS transactions with a message listener.
  6. When all outstanding replies are processed for a given order, the vendor sends a message notifying the retailer whether it can fulfill the order.
  7. The retailer receives the message from the vendor.

Figure A.1 illustrates these steps.


Figure A.1   Transactions: JMS Client Example

The program contains five classes: Retailer, Vendor, GenericSupplier, VendorMessageListener, and Order. The program also contains a main method and a method that runs the threads of the Retail, Vendor, and two supplier classes.

All the messages use the MapMessage message type. Synchronous receives are used for all message reception except for the case of the vendor processing the replies of the suppliers. These replies are processed asynchronously and demonstrate how to use transactions within a message listener.

At random intervals, the Vendor class throws an exception to simulate a database problem and cause a rollback.

All classes except Retailer use transacted sessions.

The program uses five queues. Before you run the program, create the queues and name them A, B, C, D and E.

When you run the program, specify on the command line the number of computers to be ordered. For example, on a Microsoft Windows system:

java -Djms.properties=%J2EE_HOME%\config\jms_client.properties TransactedExample 3

The output looks something like this:

Quantity to be ordered is 3
Java(TM) Message Service 1.0.2 Reference Implementation (build b14)
Java(TM) Message Service 1.0.2 Reference Implementation (build b14)
Java(TM) Message Service 1.0.2 Reference Implementation (build b14)
Java(TM) Message Service 1.0.2 Reference Implementation (build b14)
Retailer: ordered 3 computer(s)
Vendor: JMSException occurred: javax.jms.JMSException: Simulated database concurrent access exception
javax.jms.JMSException: Simulated database concurrent access 
exception at TransactedExample$Vendor.run(TransactedExample.java:300)
  Vendor: rolled back transaction 1
Vendor: Retailer ordered 3 Computer(s)
Vendor: ordered 3 Monitor(s)
Vendor: ordered 3 Hard Drive(s)
Hard Drive Supplier: Vendor ordered 3 Hard Drive(s)
Hard Drive Supplier: sent 3 Hard Drive(s)
  Vendor: committed transaction 1
Monitor Supplier: Vendor ordered 3 Monitor(s)
Monitor Supplier: sent 3 Monitor(s)
  Hard Drive Supplier: committed transaction
  Monitor Supplier: committed transaction
Vendor: Completed processing for order 1
Vendor: sent 3 computer(s)
  Vendor: committed transaction 2
Retailer: Order filled
Retailer: placing another order
Retailer: ordered 6 computer(s)
Vendor: Retailer ordered 6 Computer(s)
Vendor: ordered 6 Monitor(s)
Vendor: ordered 6 Hard Drive(s)
  Vendor: committed transaction 1
Monitor Supplier: Vendor ordered 6 Monitor(s)
Hard Drive Supplier: Vendor ordered 6 Hard Drive(s)
Hard Drive Supplier: sent 6 Hard Drive(s)
Monitor Supplier: sent 0 Monitor(s)
  Monitor Supplier: committed transaction
  Hard Drive Supplier: committed transaction
Vendor: Completed processing for order 2
Vendor: unable to send 6 computer(s)
  Vendor: committed transaction 2
Retailer: Order not filled

A.3   Acknowledgment Modes

The AckEquivExample.java program shows how the following two scenarios both ensure that a message will not be acknowledged until processing of it is complete:

With a message listener, the automatic acknowledgment happens when the onMessage method returns--that is, after message processing has finished. With a synchronous receiver, the client acknowledges the message after processing is complete. (If you use AUTO_ACKNOWLEDGE with a synchronous receive, the acknowledgment happens immediately after the receive call; if any subsequent processing steps fail, the message cannot be redelivered.)

The program contains a SynchSender class, a SynchReceiver class, an AsynchSubscriber class with a TextListener class, a MultiplePublisher class, a main method, and a method that runs the other classes' threads.

The program needs two queues, a topic, and a connection factory with a client ID, similar to the one in the example in Section A.1, "Durable Subscriptions." You can use existing administered objects or create new ones. Edit the names at the beginning of the source file before compiling if you do not use the objects already specified. You can run the program with a command on one line similar to the following example for UNIX systems:

java -Djms.properties=$J2EE_HOME/config/jms_client.properties AckEquivExample

The output looks like this:

java -Djms.properties=$J2EE_HOME/config/jms_client.properties 

AckEquivExample
Queue name is controlQueue
Queue name is jms/Queue
Topic name is jms/Topic
Connection factory name is DurableTopicCF
Java(TM) Message Service 1.0.2 Reference Implementation (build b14)
Java(TM) Message Service 1.0.2 Reference Implementation (build b14)
  SENDER: Created client-acknowledge session
  RECEIVER: Created client-acknowledge session
  SENDER: Sending message: Here is a client-acknowledge message
  RECEIVER: Processing message: Here is a client-acknowledge message
  RECEIVER: Now I'll acknowledge the message
SUBSCRIBER: Created auto-acknowledge session
PUBLISHER: Created auto-acknowledge session
PUBLISHER: Receiving synchronize messages from controlQueue; count = 1
SUBSCRIBER: Sending synchronize message to controlQueue
PUBLISHER: Received synchronize message;  expect 0 more
PUBLISHER: Publishing message: Here is an auto-acknowledge message 1
PUBLISHER: Publishing message: Here is an auto-acknowledge message 2
PUBLISHER: Publishing message: Here is an auto-acknowledge message 3
SUBSCRIBER: Processing message: Here is an auto-acknowledge message 1
SUBSCRIBER: Processing message: Here is an auto-acknowledge message 2
SUBSCRIBER: Processing message: Here is an auto-acknowledge message 3

A.4   Utility Class

The SampleUtilities class, in SampleUtilities.java, is a utility class for the other sample programs. It contains the following methods:

It also contains the class DoneLatch, which has the following methods:



TOC | Prev | Next | Index

This Tutorial contains information on the 1.3.1 version of the Java 2 Platform, Enterprise Edition.

Copyright © 2002 Sun Microsystems, Inc. All rights reserved.