Writing Simple JMS Client Applications
This section shows how to create, package, and run simple JMS client programspackaged as stand-alone application clients. These clients access a Java EE server. Theclients demonstrate the basic tasks that a JMS application must perform:
Creating a connection and a session
Creating message producers and consumers
Sending and receiving messages
In a Java EE application, some of these tasks are performed, inwhole or in part, by the container. If you learn about these tasks,you will have a good basis for understanding how a JMS application workson the Java EE platform.
This section covers the following topics:
Each example uses two programs: one that sends messages and one that receivesthem. You can run the programs in NetBeans IDE or in twoterminal windows.
When you write a JMS application to run in a Java EEapplication, you use many of the same methods in much the same sequenceas you do for a stand-alone application client. However, there are some significantdifferences.Using the JMS API in a Java EE Application describes these differences, andChapter 32, Java EE Examples Using the JMS API provides examples that illustrate them.
The examples for this section are in the following directory:
tut-install/javaeetutorial5/examples/jms/simple/
The examples are in the following four subdirectories:
producersynchconsumerasynchconsumermessagebrowser
A Simple Example of Synchronous Message Receives
This section describes the sending and receiving programs in an example that usesthereceive method to consume messages synchronously. This section then explains how tocompile, package, and run the programs using the Application Server.
The following sections describe the steps in creating and running the example:
Writing the Client Programs for the Synchronous Receive Example
The sending program,producer/src/java/Producer.java, performs the following steps:
Injects resources for a connection factory, queue, and topic:
@Resource(mappedName="jms/ConnectionFactory")private static ConnectionFactory connectionFactory;@Resource(mappedName="jms/Queue")private static Queue queue;@Resource(mappedName="jms/Topic")private static Topic topic;
Retrieves and verifies command-line arguments that specify the destination type and the number of arguments:
final int NUM_MSGS;String destType = args[0];System.out.println("Destination type is " + destType);if ( ! ( destType.equals("queue") || destType.equals("topic") ) ) { System.err.println("Argument must be \”queue\” or " + "\”topic\”"); System.exit(1);}if (args.length == 2){ NUM_MSGS = (new Integer(args[1])).intValue();} else { NUM_MSGS = 1;}Assigns either the queue or topic to a destination object, based on the specified destination type:
Destination dest = null;try { if (destType.equals("queue")) { dest = (Destination) queue; } else { dest = (Destination) topic; }} catch (Exception e) { System.err.println("Error setting destination: " + e.toString()); e.printStackTrace(); System.exit(1);}Creates aConnection and aSession:
Connection connection = connectionFactory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Creates aMessageProducer and aTextMessage:
MessageProducer producer = session.createProducer(dest);TextMessage message = session.createTextMessage();
Sends one or more messages to the destination:
for (int i = 0; i < NUM_MSGS; i++) { message.setText("This is message " + (i + 1)); System.out.println("Sending message: " + message.getText()); producer.send(message);}Sends an empty control message to indicate the end of the message stream:
producer.send(session.createMessage());
Sending an empty message of no specified type is a convenient way to indicate to the consumer that the final message has arrived.
Closes the connection in afinally block, automatically closing the session andMessageProducer:
} finally { if (connection != null) { try { connection.close(); } catch (JMSException e) { } }}
The receiving program,synchconsumer/src/java/SynchConsumer.java, performs the following steps:
Injects resources for a connection factory, queue, and topic.
Assigns either the queue or topic to a destination object, based on the specified destination type.
Creates aConnection and aSession.
Creates aMessageConsumer:
consumer = session.createConsumer(dest);
Starts the connection, causing message delivery to begin:
connection.start();
Receives the messages sent to the destination until the end-of-message-stream control message is received:
while (true) { Message m = consumer.receive(1); if (m != null) { if (m instanceof TextMessage) { message = (TextMessage) m; System.out.println("Reading message: " + message.getText()); } else { break; } }}Because the control message is not aTextMessage, the receiving program terminates thewhile loop and stops receiving messages after the control message arrives.
Closes the connection in afinally block, automatically closing the session andMessageConsumer.
Thereceive method can be used in several ways to perform a synchronousreceive. If you specify no arguments or an argument of0, the methodblocks indefinitely until a message arrives:
Message m = consumer.receive();Message m = consumer.receive(0);
For a simple client program, this may not matter. But if youdo not want your program to consume system resources unnecessarily, use a timedsynchronous receive. Do one of the following:
Call thereceive method with a timeout argument greater than0:
Message m = consumer.receive(1); // 1 millisecond
Call thereceiveNoWait method, which receives a message only if one is available:
Message m = consumer.receiveNoWait();
TheSynchConsumer program uses an indefinitewhile loop to receive messages, callingreceive with a timeout argument. CallingreceiveNoWait would have the same effect.
Starting the JMS Provider
When you use the Application Server, your JMS provider is the ApplicationServer. Start the server as described inStarting and Stopping the Application Server.
Creating JMS Administered Objects for the Synchronous Receive Example
Creating the JMS administered objects for this section involves the following:
If you built and ran theSimpleMessage example inChapter 23, A Message-Driven Bean Example and did notdelete the resources afterward, you need to create only the topic resource.
You can create these objects using the Ant tool. To create allthe resources, do the following:
In a terminal window, go to theproducer directory:
cd producer
To create all the resources, type the following command:
ant create-resources
To create only the topic resource, type the following command:
ant create-topic
These Ant targets use theasadmincreate-jms-resource command to create the connectionfactory and the destination resources.
To verify that the resources have been created, use the following command:
asadmin list-jms-resources
The output looks like this:
jms/Queuejms/Topicjms/ConnectionFactoryCommand list-jms-resources executed successfully.
Compiling and Packaging the Clients for the Synchronous Receive Example
The simplest way to run these examples using the Application Server isto package each one in an application client JAR file. The application client JARfile requires a manifest file, located in thesrc/conf directory for each example,along with the.class file.
Thebuild.xml file for each example contains Ant targets that compile and packagethe example. The targets place the.class file for the example inthebuild/jar directory. Then the targets use thejar command to package theclass file and the manifest file in an application client JAR file.
To compile and package theProducer andSynchConsumer examples using NetBeans IDE,follow these steps:
In NetBeans IDE, choose Open Project from the File menu.
In the Open Project dialog, navigate totut-install/javaeetutorial5/examples/jms/simple/.
Select theproducer folder.
Select the Open as Main Project check box.
Click Open Project.
Right-click the project and choose Build.
In NetBeans IDE, choose Open Project from the File menu.
In the Open Project dialog, navigate totut-install/javaeetutorial5/examples/jms/simple/.
Select thesynchconsumer folder.
Select the Open as Main Project check box.
Click Open Project.
Right-click the project and choose Build.
To compile and package theProducer andSynchConsumer examples using Ant, followthese steps:
In a terminal window, go to theproducer directory:
cd producer
Type the following command:
ant
In a terminal window, go to thesynchconsumer directory:
cd ../synchconsumer
Type the following command:
ant
The targets place the application client JAR file in thedist directory foreach example.
Running the Clients for the Synchronous Receive Example
To run the sample programs using NetBeans IDE, follow these steps.
Run theProducer example:
Right-click theproducer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
queue 3
Click OK.
Right-click the project and choose Run.
The output of the program looks like this:
Destination type is queueSending message: This is message 1Sending message: This is message 2Sending message: This is message 3
The messages are now in the queue, waiting to be received.
Now run theSynchConsumer example:
Right-click thesynchconsumer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
queue
Click OK.
Right-click the project and choose Run.
The output of the program looks like this:
Destination type is queueReading message: This is message 1Reading message: This is message 2Reading message: This is message 3
Now try running the programs in the opposite order. Right-click thesynchconsumer project and choose Run.
The Output pane displays the destination type and then appears to hang, waiting for messages.
Right-click theproducer project and choose Run.
The Output pane shows the output of both programs, in two different tabs.
Now run theProducer example using a topic instead of a queue.
Right-click theproducer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
topic 3
Click OK.
Right-click the project and choose Run.
The output of the program looks like this:
Destination type is topicSending message: This is message 1Sending message: This is message 2Sending message: This is message 3
Now run theSynchConsumer example using the topic.
Right-click thesynchconsumer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
topic
Click OK.
Right-click the project and choose Run.
The result, however, is different. Because you are using a topic, messages that were sent before you started the consumer cannot be received. (SeePublish/Subscribe Messaging Domain, for details.) Instead of receiving the messages, the program appears to hang.
Run theProducer example again. Right-click theproducer project and choose Run.
Now theSynchConsumer example receives the messages:
Destination type is topicReading message: This is message 1Reading message: This is message 2Reading message: This is message 3
You can also run the sample programs using theappclient command. Each ofthe programs takes one or more command-line arguments: a destination type and, forProducer, a number of messages.
To run the clients using theappclient command, follow these steps:
In a terminal window, go to theproducer/dist directory:
cd ../producer/dist
Run theProducer program, sending three messages to the queue:
appclient -client producer.jar queue 3
The output of the program looks like this:
Destination type is queueSending message: This is message 1Sending message: This is message 2Sending message: This is message 3
The messages are now in the queue, waiting to be received.
In the same window, go to thesynchconsumer/dist directory:
cd ../../synchconsumer/dist
Run theSynchConsumer program, specifying the queue:
appclient -client synchconsumer.jar queue
The output of the program looks like this:
Destination type is queueReading message: This is message 1Reading message: This is message 2Reading message: This is message 3
Now try running the programs in the opposite order. Run theSynchConsumer program. It displays the destination type and then appears to hang, waiting for messages.
appclient -client synchconsumer.jar queue
In a different terminal window, run theProducer program.
cdtut-install/javaeetutorial5/examples/jms/simple/producer/dist appclient -client producer.jar queue 3
When the messages have been sent, theSynchConsumer program receives them and exits.
Now run theProducer program using a topic instead of a queue:
appclient -client producer.jar topic 3
The output of the program looks like this:
Destination type is topicSending message: This is message 1Sending message: This is message 2Sending message: This is message 3
Now run theSynchConsumer program using the topic:
appclient -client synchconsumer.jar topic
The result, however, is different. Because you are using a topic, messages that were sent before you started the consumer cannot be received. (SeePublish/Subscribe Messaging Domain, for details.) Instead of receiving the messages, the program appears to hang.
Run theProducer program again. Now theSynchConsumer program receives the messages:
Destination type is topicReading message: This is message 1Reading message: This is message 2Reading message: This is message 3
Because the examples use the common interfaces, you can run them using eithera queue or a topic.
A Simple Example of Asynchronous Message Consumption
This section describes the receiving programs in an example that uses a messagelistener to consume messages asynchronously. This section then explains how to compile andrun the programs using the Application Server.
The following sections describe the steps in creating and running the example:
Writing the Client Programs for the Asynchronous Receive Example
The sending program isproducer/src/java/Producer.java, the same program used in the example inA Simple Example of Synchronous Message Receives.
An asynchronous consumer normally runs indefinitely. This one runs until the user typesthe letterq orQ to stop the program.
The receiving program,asynchconsumer/src/java/AsynchConsumer.java, performs the following steps:
Injects resources for a connection factory, queue, and topic.
Assigns either the queue or topic to a destination object, based on the specified destination type.
Creates aConnection and aSession.
Creates aMessageConsumer.
Creates an instance of theTextListener class and registers it as the message listener for theMessageConsumer:
listener = new TextListener();consumer.setMessageListener(listener);
Starts the connection, causing message delivery to begin.
Listens for the messages published to the destination, stopping when the user types the characterq orQ:
System.out.println("To end program, type Q or q, " + "then <return>");inputStreamReader = new InputStreamReader(System.in);while (!((answer == ’q’) || (answer == ’Q’))) { try { answer = (char) inputStreamReader.read(); } catch (IOException e) { System.out.println("I/O exception: " + e.toString()); }}Closes the connection, which automatically closes the session andMessageConsumer.
The message listener,asynchconsumer/src/java/TextListener.java, follows these steps:
When a message arrives, theonMessage method is called automatically.
TheonMessage method converts the incoming message to aTextMessage and displays its content. If the message is not a text message, it reports this fact:
public void onMessage(Message message) { TextMessage msg = null; try { if (message instanceof TextMessage) { msg = (TextMessage) message; System.out.println("Reading message: " + msg.getText()); } else { System.out.println("Message is not a " + "TextMessage"); } } catch (JMSException e) { System.out.println("JMSException in onMessage(): " + e.toString()); } catch (Throwable t) { System.out.println("Exception in onMessage():" + t.getMessage()); }}
You will use the connection factory and destinations you created inCreating JMS Administered Objects for the Synchronous Receive Example.
Compiling and Packaging theAsynchConsumer Client
To compile and package theAsynchConsumer example using NetBeans IDE, follow these steps:
In NetBeans IDE, choose Open Project from the File menu.
In the Open Project dialog, navigate totut-install/javaeetutorial5/examples/jms/simple/.
Select theasynchconsumer folder.
Select the Open as Main Project check box.
Click Open Project.
Right-click the project and choose Build.
To compile and package theAsynchConsumer example using Ant, follow these steps:
In a terminal window, go to theasynchconsumer directory:
cd ../../asynchconsumer
Type the following command:
ant
The targets package both the main class and the message listener class inthe JAR file and place the file in thedist directory for theexample.
Running the Clients for the Asynchronous Receive Example
To run the programs using NetBeans IDE, follow these steps.
Run theAsynchConsumer example:
Right-click theasynchconsumer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
topic
Click OK.
Right-click the project and choose Run.
The program displays the following lines and appears to hang:
Destination type is topicTo end program, type Q or q, then <return>
Now run theProducer example:
Right-click theproducer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
topic 3
Click OK.
Right-click the project and choose Run.
The output of the program looks like this:
Destination type is topicSending message: This is message 1Sending message: This is message 2Sending message: This is message 3
In the other window, theAsynchConsumer program displays the following:
Destination type is topicTo end program, type Q or q, then <return>Reading message: This is message 1Reading message: This is message 2Reading message: This is message 3Message is not a TextMessage
The last line appears because the program has received the non-text control message sent by theProducer program.
TypeQ orq in the Output window and press Return to stop the program.
Now run the programs using a queue. In this case, as with the synchronous example, you can run theProducer program first, because there is no timing dependency between the sender and receiver.
Right-click theproducer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
queue 3
Click OK.
Right-click the project and choose Run.
The output of the program looks like this:
Destination type is queueSending message: This is message 1Sending message: This is message 2Sending message: This is message 3
Run theAsynchConsumer program.
Right-click theasynchconsumer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
queue
Click OK.
Right-click the project and choose Run.
The output of the program looks like this:
Destination type is queueTo end program, type Q or q, then <return>Reading message: This is message 1Reading message: This is message 2Reading message: This is message 3Message is not a TextMessage
TypeQ orq in the Output window and press Return to stop the program.
To run the clients using theappclient command, follow these steps:
Run theAsynchConsumer program, specifying thetopic destination type.
cd dist appclient -client asynchconsumer.jar topic
The program displays the following lines and appears to hang:
Destination type is topicTo end program, type Q or q, then <return>
In the terminal window where you ran theProducer program previously, run the program again, sending three messages. The command looks like this:
appclient -client producer.jar topic 3
The output of the program looks like this:
Destination type is topicSending message: This is message 1Sending message: This is message 2Sending message: This is message 3
In the other window, theAsynchConsumer program displays the following:
Destination type is topicTo end program, type Q or q, then <return>Reading message: This is message 1Reading message: This is message 2Reading message: This is message 3Message is not a TextMessage
The last line appears because the program has received the non-text control message sent by theProducer program.
TypeQ orq and press Return to stop the program.
Now run the programs using a queue. In this case, as with the synchronous example, you can run theProducer program first, because there is no timing dependency between the sender and receiver:
appclient -client producer.jar queue 3
The output of the program looks like this:
Destination type is queueSending message: This is message 1Sending message: This is message 2Sending message: This is message 3
Run theAsynchConsumer program:
appclient -client asynchconsumer.jar queue
The output of the program looks like this:
Destination type is queueTo end program, type Q or q, then <return>Reading message: This is message 1Reading message: This is message 2Reading message: This is message 3Message is not a TextMessage
TypeQ orq to stop the program.
A Simple Example of Browsing Messages in a Queue
This section describes an example that creates aQueueBrowser object to examine messageson a queue, as described inJMS Queue Browsers. This section then explains howto compile, package, and run the example using the Application Server.
The following sections describe the steps in creating and running the example:
Writing the Client Program for the Queue Browser Example
To create aQueueBrowser for a queue, you call theSession.createBrowser method withthe queue as the argument. You obtain the messages in the queue asanEnumeration object. You can then iterate through theEnumeration object and display thecontents of each message.
Themessagebrowser/src/java/MessageBrowser.java program performs the following steps:
Injects resources for a connection factory and a queue.
Creates aConnection and aSession.
Creates aQueueBrowser:
QueueBrowser browser = session.createBrowser(queue);
Retrieves theEnumeration that contains the messages:
Enumeration msgs = browser.getEnumeration();
Verifies that theEnumeration contains messages, then displays the contents of the messages:
if ( !msgs.hasMoreElements() ) { System.out.println("No messages in queue");} else { while (msgs.hasMoreElements()) { Message tempMsg = (Message)msgs.nextElement(); System.out.println("Message: " + tempMsg); }}Closes the connection, which automatically closes the session andQueueBrowser.
The format in which the message contents appear is implementation-specific. In the ApplicationServer, the message format looks like this:
Message contents: Text: This is message 3Class: com.sun.messaging.jmq.jmsclient.TextMessageImplgetJMSMessageID(): ID:14-129.148.71.199(f9:86:a2:d5:46:9b)-40814-1129061034355getJMSTimestamp(): 1129061034355getJMSCorrelationID(): nullJMSReplyTo: nullJMSDestination: PhysicalQueuegetJMSDeliveryMode(): PERSISTENTgetJMSRedelivered(): falsegetJMSType(): nullgetJMSExpiration(): 0getJMSPriority(): 4Properties: null
You will use the connection factory and queue you created inCreating JMS Administered Objects for the Synchronous Receive Example.
Compiling and Packaging theMessageBrowser Client
To compile and package theMessageBrowser example using NetBeans IDE, follow these steps:
In NetBeans IDE, choose Open Project from the File menu.
In the Open Project dialog, navigate totut-install/javaeetutorial5/examples/jms/simple/.
Select themessagebrowser folder.
Select the Open as Main Project check box.
Click Open Project.
Right-click the project and choose Build.
To compile and package theMessageBrowser example using Ant, follow these steps:
In a terminal window, go to themessagebrowser directory. If you are currently in theasynchconsumer/dist directory, you need to go up two levels:
cd ../../messagebrowser
Type the following command:
ant
The targets place the application client JAR file in thedist directory forthe example.
You also need theProducer example to send the message to the queue,and one of the consumer programs to consume the messages after you inspectthem. If you did not do so already, package these examples.
Running the Clients for the Queue Browser Example
To run the programs using NetBeans IDE, follow these steps.
Run theProducer program, sending one message to the queue:
Right-click theproducer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
queue
Click OK.
Right-click the project and choose Run.
The output of the program looks like this:
Destination type is queueSending message: This is message 1
Run theMessageBrowser program. Right-click themessagebrowser project and choose Run.
The output of the program looks like this:
Message: Text: This is message 1Class: com.sun.messaging.jmq.jmsclient.TextMessageImplgetJMSMessageID(): ID:12-129.148.71.199(8c:34:4a:1a:1b:b8)-40883-1129062957611getJMSTimestamp(): 1129062957611getJMSCorrelationID(): nullJMSReplyTo: nullJMSDestination: PhysicalQueuegetJMSDeliveryMode(): PERSISTENTgetJMSRedelivered(): falsegetJMSType(): nullgetJMSExpiration(): 0getJMSPriority(): 4Properties: nullMessage: Class: com.sun.messaging.jmq.jmsclient.MessageImplgetJMSMessageID(): ID:13-129.148.71.199(8c:34:4a:1a:1b:b8)-40883-1129062957616getJMSTimestamp(): 1129062957616getJMSCorrelationID(): nullJMSReplyTo: nullJMSDestination: PhysicalQueuegetJMSDeliveryMode(): PERSISTENTgetJMSRedelivered(): falsegetJMSType(): nullgetJMSExpiration(): 0getJMSPriority(): 4Properties: null
The first message is theTextMessage, and the second is the non-text control message.
Run theSynchConsumer program to consume the messages.
Right-click thesynchconsumer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
queue
Click OK.
Right-click the project and choose Run.
The output of the program looks like this:
Destination type is queueReading message: This is message 1
To run the clients using theappclient command, follow these steps. You maywant to use two terminal windows.
Go to theproducer/dist directory.
Run theProducer program, sending one message to the queue:
appclient -client producer.jar queue
The output of the program looks like this:
Destination type is queueSending message: This is message 1
Go to themessagebrowser/dist directory.
Run theMessageBrowser program:
appclient -client messagebrowser.jar
The output of the program looks like this:
Message: Text: This is message 1Class: com.sun.messaging.jmq.jmsclient.TextMessageImplgetJMSMessageID(): ID:12-129.148.71.199(8c:34:4a:1a:1b:b8)-40883-1129062957611getJMSTimestamp(): 1129062957611getJMSCorrelationID(): nullJMSReplyTo: nullJMSDestination: PhysicalQueuegetJMSDeliveryMode(): PERSISTENTgetJMSRedelivered(): falsegetJMSType(): nullgetJMSExpiration(): 0getJMSPriority(): 4Properties: nullMessage: Class: com.sun.messaging.jmq.jmsclient.MessageImplgetJMSMessageID(): ID:13-129.148.71.199(8c:34:4a:1a:1b:b8)-40883-1129062957616getJMSTimestamp(): 1129062957616getJMSCorrelationID(): nullJMSReplyTo: nullJMSDestination: PhysicalQueuegetJMSDeliveryMode(): PERSISTENTgetJMSRedelivered(): falsegetJMSType(): nullgetJMSExpiration(): 0getJMSPriority(): 4Properties: null
The first message is theTextMessage, and the second is the non-text control message.
Go to thesynchconsumer/dist directory.
Run theSynchConsumer program to consume the messages:
appclient -client synchconsumer.jar queue
The output of the program looks like this:
Destination type is queueReading message: This is message 1
Running JMS Client Programs on Multiple Systems
JMS client programs using the Application Server can exchange messages with each otherwhen they are running on different systems in a network. The systems mustbe visible to each other by name (the UNIX host name orthe Microsoft Windows computer name) and must both be running the Application Server.You do not have to install the tutorial examples on both systems; youcan use the examples installed on one system if you can access itsfile system from the other system.
Note -Any mechanism for exchanging messages between systems is specific to the Java EEserver implementation. This tutorial describes how to use the Application Server for thispurpose.
Suppose that you want to run theProducer program on one system,earth,and theSynchConsumer program on another system,jupiter. Before you can do so,you need to perform these tasks:
Create two new connection factories
Edit the source code for the two examples
Recompile and repackage the examples
Note -A limitation in the JMS provider in the Application Server may cause a runtime failure to create a connection to systems that use the Dynamic Host Configuration Protocol (DHCP) to obtain an IP address. You can, however, create a connectionfrom a system that uses DHCPto a system that does not use DHCP. In the examples in this tutorial,earth can be a system that uses DHCP, andjupiter can be a system that does not use DHCP.
Before you begin, start the server on both systems:
Start the Application Server onearth.
Start the Application Server onjupiter.
Creating Administered Objects for Multiple Systems
To run these programs, you must do the following:
You do not have to install the tutorial on both systems, butyou must be able to access the filesystem where it is installed. Youmay find it more convenient to install the tutorial on both systems ifthe two systems use different operating systems (for example, Windows and Solaris). Otherwise youwill have to edit the filetut-install/javaeetutorial5/examples/bp-project/build.properties and change the location ofthejavaee.home property each time you build or run a program on adifferent system.
To create a new connection factory onjupiter, perform these steps:
From a command shell onjupiter, go to the directorytut-install/javaeetutorial5/examples/jms/simple/producer/.
Type the following command:
ant create-local-factory
Thecreate-local-factory target, defined in thebuild.xml file for theProducer example,creates a connection factory namedjms/JupiterConnectionFactory.
To create a new connection factory onearth that points to the connectionfactory onjupiter, perform these steps:
From a command shell onearth, go to the directorytut-install/javaeetutorial5/examples/jms/simple/producer/.
Type the following command:
ant create-remote-factory -Dsys=remote-system-name
Replaceremote-system-name with the actual name of the remote system.
Thecreate-remote-factory target, defined in thebuild.xml file for theProducer example,also creates a connection factory namedjms/JupiterConnectionFactory. In addition, it sets theAddressList propertyfor this factory to the name of the remote system.
If you have already been working on eitherearth orjupiter, youhave the queue and topic on one system. On the system that doesnot have the queue and topic, type the following command:
ant create-resources
When you run the programs, they will work as shown inFigure 31-6.The program run onearth needs the queue onearth only inorder that the resource injection will succeed. The connection, session, and message producer areall created onjupiter using the connection factory that points tojupiter. Themessages sent fromearth will be received onjupiter.
Figure 31-6 Sending Messages from One System to Another

Editing, Recompiling, Repackaging, and Running the Programs
These steps assume that you have the tutorial installed on only one ofthe two systems you are using and that you are able toaccess the file system ofjupiter fromearth or vice versa.
After you create the connection factories, edit the source files to specify thenew connection factory. Then recompile, repackage, and run the programs. Perform the followingsteps:
Open the following file in a text editor:
tut-installjavaeetutorial5/examples/jms/simple/producer/src/java/Producer.java
Find the following line:
@Resource(mappedName="jms/ConnectionFactory")
Change the line to the following:
@Resource(mappedName="jms/JupiterConnectionFactory")
Recompile and repackage theProducer example onearth.
If you are using NetBeans IDE, right-click theproducer project and choose Clean and Build.
If you are using Ant, type the following:
ant
Open the following file in a text editor:
tut-installjavaeetutorial5/examples/jms/simple/synchconsumer/src/java/SynchConsumer.java
Repeat steps 2 and 3.
Recompile and repackage theSynchConsumer example onjupiter.
If you are using NetBeans IDE, right-click thesynchconsumer project and choose Clean and Build.
If you are using Ant, go to thesynchconsumer directory and type:
ant
Onearth, runProducer. If you are using NetBeans IDE onearth, perform these steps:
Right-click theproducer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
queue 3
Click OK.
Right-click the project and choose Run.
If you are using theappclient command, go to theproducer/dist directory and type the following:
appclient -client producer.jar queue 3
Onjupiter, runSynchConsumer. If you are using NetBeans IDE onjupiter, perform these steps:
Right-click thesynchconsumer project and choose Properties.
Select Run from the Categories tree.
In the Arguments field, type the following:
queue
Click OK.
Right-click the project and choose Run.
If you are using theappclient command, go to thesynchconsumer/dist directory and type the following:
appclient -client synchconsumer.jar queue
For examples showing how to deploy Java EE applications on two different systems,seeAn Application Example That Consumes Messages from a Remote Server andAn Application Example That Deploys a Message-Driven Bean on Two Servers.
Deleting the Connection Factory and Stopping the Server
You will need the connection factoryjms/JupiterConnectionFactory inChapter 32, Java EE Examples Using the JMS API. However, if you wishto delete it, go to theproducer directory and type the following command:
ant delete-remote-factory
Remember to delete the connection factory on both systems.
You can also use Ant targets in theproducer/build.xml file to delete thedestinations and connection factories you created inCreating JMS Administered Objects for the Synchronous Receive Example. However, it is recommendedthat you keep them, because they will be used in most of theexamples inChapter 32, Java EE Examples Using the JMS API. After you have created them, they will be available wheneveryou restart the Application Server.
To delete the class and JAR files for each program using NetBeansIDE, right-click each project and choose Clean.
To delete the class and JAR files for each program using Ant,type the following:
ant clean
You can also stop the Application Server, but you will need itto run the sample programs in the next section.