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

48.  Java Message Service Examples

Writing Robust JMS Applications

A Message Acknowledgment Example

To Run ackequivexample Using NetBeans IDE

To Run ackequivexample Using Ant

A Durable Subscription Example

To Run durablesubscriberexample Using NetBeans IDE

To Run durablesubscriberexample Using Ant

A Local Transaction Example

To Run transactedexample Using NetBeans IDE

To Run transactedexample Using Ant and the appclient Command

An Application That Uses the JMS API with a Session Bean

Writing the Application Components for the clientsessionmdb Example

Coding the Application Client: MyAppClient.java

Coding the Publisher Session Bean

Coding the Message-Driven Bean: MessageBean.java

Creating Resources for the clientsessionmdb Example

Running the clientsessionmdb Example

To Run the clientsessionmdb Example Using NetBeans IDE

To Run the clientsessionmdb Example Using Ant

An Application That Uses the JMS API with an Entity

Overview of the clientmdbentity Example Application

Writing the Application Components for the clientmdbentity Example

Coding the Application Client: HumanResourceClient.java

Coding the Message-Driven Beans for the clientmdbentity Example

Coding the Entity Class for the clientmdbentity Example

Creating Resources for the clientmdbentity Example

Running the clientmdbentity Example

To Run the clientmdbentity Example Using NetBeans IDE

To Run the clientmdbentity Example Using Ant

An Application Example That Consumes Messages from a Remote Server

Overview of the consumeremote Example Modules

Writing the Module Components for the consumeremote Example

Creating Resources for the consumeremote Example

Using Two Application Servers for the consumeremote Example

Running the consumeremote Example

To Run the consumeremote Example Using NetBeans IDE

To Run the consumeremote Example Using Ant

An Application Example That Deploys a Message-Driven Bean on Two Servers

Overview of the sendremote Example Modules

Writing the Module Components for the sendremote Example

Coding the Application Client: MultiAppServerClient.java

Coding the Message-Driven Bean: ReplyMsgBean.java

Creating Resources for the sendremote Example

To Enable Deployment on the Remote System

To Use Two Application Servers for the sendremote Example

Running the sendremote Example

To Run the sendremote Example Using NetBeans IDE

To Run the sendremote Example Using Ant

To Disable Deployment on the Remote System

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

 

Writing Simple JMS Applications

This section shows how to create, package, and run simple JMS clients that are packaged as application clients and deployed to a Java EE server. The clients demonstrate the basic tasks 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, in whole or in part, by the container. If you learn about these tasks, you will have a good basis for understanding how a JMS application works on the Java EE platform.

Each example uses two clients: one that sends messages and one that receives them. You can run the clients in NetBeans IDE or in two terminal windows.

When you write a JMS client to run in an enterprise bean application, you use many of the same methods in much the same sequence as for an application client. However, there are some significant differences. Using the JMS API in Java EE Applications describes these differences, and this chapter provides examples that illustrate them.

The examples for this section are in the tut-install/examples/jms/simple/ directory, under the following four subdirectories:

producer
synchconsumer
asynchconsumer
messagebrowser

A Simple Example of Synchronous Message Receives

This section describes the sending and receiving clients in an example that uses the receive method to consume messages synchronously. This section then explains how to compile, package, and run the clients using the GlassFish Server.

The following subsections describe the steps in creating and running the example.

Writing the Clients for the Synchronous Receive Example

The sending client, producer/src/java/Producer.java, performs the following steps:

  1. Injects resources for a connection factory, queue, and topic:

    @Resource(lookup = "jms/ConnectionFactory")
    private static ConnectionFactory connectionFactory;
    @Resource(lookup = "jms/Queue")private static Queue queue;
    @Resource(lookup = "jms/Topic")private static Topic topic;
  2. 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;
    }
  3. Assigns either the queue or the 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);
    }
  4. Creates a Connection and a Session:

    Connection connection = connectionFactory.createConnection(); 
    Session session = connection.createSession(
                false, 
                Session.AUTO_ACKNOWLEDGE);
  5. Creates a MessageProducer and a TextMessage:

    MessageProducer producer = session.createProducer(dest);
    TextMessage message = session.createTextMessage();
  6. Sends one or more messages to the destination:

    for (int i = 0; i < NUM_MSGS; i++) { 
        message.setText("This is message " + (i + 1) + " from producer"); 
        System.out.println("Sending message: " + message.getText()); 
        producer.send(message);
    }
  7. 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.

  8. Closes the connection in a finally block, automatically closing the session and MessageProducer:

    } finally { 
        if (connection != null) { 
            try { connection.close(); } 
            catch (JMSException e) { } 
        }
    }

The receiving client, synchconsumer/src/java/SynchConsumer.java, performs the following steps:

  1. Injects resources for a connection factory, queue, and topic.

  2. Assigns either the queue or the topic to a destination object, based on the specified destination type.

  3. Creates a Connection and a Session.

  4. Creates a MessageConsumer:

    consumer = session.createConsumer(dest);
  5. Starts the connection, causing message delivery to begin:

    connection.start();
  6. 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 a TextMessage, the receiving client terminates the while loop and stops receiving messages after the control message arrives.

  7. Closes the connection in a finally block, automatically closing the session and MessageConsumer.

The receive method can be used in several ways to perform a synchronous receive. If you specify no arguments or an argument of 0, the method blocks indefinitely until a message arrives:

Message m = consumer.receive();
Message m = consumer.receive(0);

For a simple client, this may not matter. But if you do not want your application to consume system resources unnecessarily, use a timed synchronous receive. Do one of the following:

  • Call the receive method with a timeout argument greater than 0:

    Message m = consumer.receive(1); // 1 millisecond
  • Call the receiveNoWait method, which receives a message only if one is available:

    Message m = consumer.receiveNoWait();

The SynchConsumer client uses an indefinite while loop to receive messages, calling receive with a timeout argument. Calling receiveNoWait would have the same effect.

Starting the JMS Provider

When you use the GlassFish Server, your JMS provider is the GlassFish Server. Start the server as described in Starting and Stopping the GlassFish Server.

JMS Administered Objects for the Synchronous Receive Example

This example uses the following JMS administered objects:

  • A connection factory

  • Two destination resources: a topic and a queue

NetBeans IDE and the Ant tasks for the JMS examples create needed JMS resources when you deploy the applications, using a file named setup/glassfish-resources.xml. This file is most easily created using NetBeans IDE, although you can create it by hand.

You can also use the asadmin create-jms-resource command to create resources, the asadmin list-jms-resources command to display their names, and the asadmin delete-jms-resource command to remove them.

To Create JMS Resources Using NetBeans IDE

Follow these steps to create a JMS resource in GlassFish Server using NetBeans IDE. Repeat these steps for each resource you need.

The example applications in this chapter already have the resources, so you will need to follow these steps only when you create your own applications.

  1. Right-click the project for which you want to create resources and choose New, then choose Other.

    The New File wizard opens.

  2. Under Categories, select GlassFish.
  3. Under File Types, select JMS Resource.

    The General Attributes - JMS Resource page opens.

  4. In the JNDI Name field, type the name of the resource.

    By convention, JMS resource names begin with jms/.

  5. Select the radio button for the resource type.

    Normally, this is either javax.jms.Queue, javax.jms.Topic, or javax.jms.ConnectionFactory.

  6. Click Next.

    The JMS Properties page opens.

  7. For a queue or topic, type a name for a physical queue in the Value field for the Name property.

    You can type any value for this required field.

    Connection factories have no required properties. In a few situations, discussed in later sections, you may need to specify a property.

  8. Click Finish.

    A file named glassfish-resources.xml is created in your project, in a directory named setup. In the project pane, you can find it under the Server Resources node. If this file exists, resources are created automatically by NetBeans IDE when you deploy the project.

To Delete JMS Resources Using NetBeans IDE

  1. In the Services pane, expand the Servers node, then expand the GlassFish Server 3+ node.
  2. Expand the Resources node, then expand the Connector Resources node.
  3. Expand the Admin Object Resources node.
  4. Right-click any destination you want to remove and select Unregister.
  5. Expand the Connector Connection Pools node.
  6. Right-click any connection factory you want to remove and select Unregister.

    Every connection factory has both a connector connection pool and an associated connector resource. When you remove the connector connection pool, the resource is removed automatically. You can verify the removal by expanding the Connector Resources node.

Running the Clients for the Synchronous Receive Example

To run these examples using the GlassFish Server, package each one in an application client JAR file. The application client JAR file requires a manifest file, located in the src/conf directory for each example, along with the .class file.

The build.xml file for each example contains Ant targets that compile, package, and deploy the example. The targets place the .class file for the example in the build/jar directory. Then the targets use the jar command to package the class file and the manifest file in an application client JAR file.

Because the examples use the common interfaces, you can run them using either a queue or a topic.

To Build and Package the Clients for the Synchronous Receive Example Using NetBeans IDE

  1. From the File menu, choose Open Project.
  2. In the Open Project dialog, navigate to:
    tut-install/examples/jms/simple/
  3. Select the producer folder.
  4. Select the Open as Main Project check box.
  5. Click Open Project.
  6. In the Projects tab, right-click the project and select Build.
  7. From the File menu, choose Open Project again.
  8. Select the synchconsumer folder.
  9. Select the Open as Main Project check box.
  10. Click Open Project.
  11. In the Projects tab, right-click the project and select Build.

To Deploy and Run the Clients for the Synchronous Receive Example Using NetBeans IDE

  1. Deploy and run the Producer example:
    1. Right-click the producer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      queue 3
    4. Click OK.
    5. Right-click the project and select Run.

      The output of the program looks like this (along with some additional output):

      Destination type is queue
      Sending message: This is message 1 from producer
      Sending message: This is message 2 from producer
      Sending message: This is message 3 from producer

      The messages are now in the queue, waiting to be received.


      Note - When you run an application client, the command often takes a long time to complete.


  2. Now deploy and run the SynchConsumer example:
    1. Right-click the synchconsumer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      queue
    4. Click OK.
    5. Right-click the project and select Run.

      The output of the program looks like this (along with some additional output):

      Destination type is queue
      Reading message: This is message 1 from producer
      Reading message: This is message 2 from producer
      Reading message: This is message 3 from producer
  3. Now try running the programs in the opposite order. Right-click the synchconsumer project and select Run.

    The Output pane displays the destination type and then appears to hang, waiting for messages.

  4. Right-click the producer project and select Run.

    When the messages have been sent, the SynchConsumer client receives them and exits. The Output pane shows the output of both programs, in two different tabs.

  5. Now run the Producer example using a topic instead of a queue.
    1. Right-click the producer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      topic 3
    4. Click OK.
    5. Right-click the project and select Run.

      The output looks like this (along with some additional output):

      Destination type is topic
      Sending message: This is message 1 from producer
      Sending message: This is message 2 from producer
      Sending message: This is message 3 from producer
  6. Now run the SynchConsumer example using the topic.
    1. Right-click the synchconsumer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      topic
    4. Click OK.
    5. Right-click the project and select Run.

      The result, however, is different. Because you are using a topic, messages that were sent before you started the consumer cannot be received. (See Publish/Subscribe Messaging Domain for details.) Instead of receiving the messages, the program appears to hang.

  7. Run the Producer example again. Right-click the producer project and select Run.

    Now the SynchConsumer example receives the messages:

    Destination type is topic
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer

To Build and Package the Clients for the Synchronous Receive Example Using Ant

  1. In a terminal window, go to the producer directory:
    cd producer
  2. Type the following command:
    ant
  3. In a terminal window, go to the synchconsumer directory:
    cd ../synchconsumer
  4. Type the following command:
    ant

    The targets place the application client JAR file in the dist directory for each example.

To Deploy and Run the Clients for the Synchronous Receive Example Using Ant and the appclient Command

You can run the clients using the appclient command. The build.xml file for each project includes a target that creates resources, deploys the client, and then retrieves the client stubs that the appclient command uses. Each of the clients takes one or more command-line arguments: a destination type and, for Producer, a number of messages.

To build, deploy, and run the Producer and SynchConsumer examples using Ant and the appclient command, follow these steps.

To run the clients, you need two terminal windows.

  1. In a terminal window, go to the producer directory:
    cd ../producer
  2. Create any needed resources, deploy the client JAR file to the GlassFish Server, then retrieve the client stubs:
    ant getclient

    Ignore the message that states that the application is deployed at a URL.

  3. Run the Producer program, sending three messages to the queue:
    appclient -client client-jar/producerClient.jar queue 3

    The output of the program looks like this (along with some additional output):

    Destination type is queue
    Sending message: This is message 1 from producer
    Sending message: This is message 2 from producer
    Sending message: This is message 3 from producer

    The messages are now in the queue, waiting to be received.


    Note - When you run an application client, the command often takes a long time to complete.


  4. In the same window, go to the synchconsumer directory:
    cd ../synchconsumer
  5. Deploy the client JAR file to the GlassFish Server, then retrieve the client stubs:
    ant getclient

    Ignore the message that states that the application is deployed at a URL.

  6. Run the SynchConsumer client, specifying the queue:
    appclient -client client-jar/synchconsumerClient.jar queue

    The output of the client looks like this (along with some additional output):

    Destination type is queue
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer
  7. Now try running the clients in the opposite order. Run the SynchConsumer client:
    appclient -client client-jar/synchconsumerClient.jar queue

    The client displays the destination type and then appears to hang, waiting for messages.

  8. In a different terminal window, run the Producer client.
    cd tut-install/examples/jms/simple/producer
    appclient -client client-jar/producerClient.jar queue 3

    When the messages have been sent, the SynchConsumer client receives them and exits.

  9. Now run the Producer client using a topic instead of a queue:
    appclient -client client-jar/producerClient.jar topic 3

    The output of the client looks like this (along with some additional output):

    Destination type is topic
    Sending message: This is message 1 from producer
    Sending message: This is message 2 from producer
    Sending message: This is message 3 from producer
  10. Now run the SynchConsumer client using the topic:
    appclient -client client-jar/synchconsumerClient.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. (See Publish/Subscribe Messaging Domain for details.) Instead of receiving the messages, the client appears to hang.

  11. Run the Producer client again.

    Now the SynchConsumer client receives the messages (along with some additional output):

    Destination type is topic
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer

A Simple Example of Asynchronous Message Consumption

This section describes the receiving clients in an example that uses a message listener to consume messages asynchronously. This section then explains how to compile and run the clients using the GlassFish Server.

Writing the Clients for the Asynchronous Receive Example

The sending client is producer/src/java/Producer.java, the same client used in the example in A Simple Example of Synchronous Message Receives.

An asynchronous consumer normally runs indefinitely. This one runs until the user types the character q or Q to stop the client.

The receiving client, asynchconsumer/src/java/AsynchConsumer.java, performs the following steps:

  1. Injects resources for a connection factory, queue, and topic.

  2. Assigns either the queue or the topic to a destination object, based on the specified destination type.

  3. Creates a Connection and a Session.

  4. Creates a MessageConsumer.

  5. Creates an instance of the TextListener class and registers it as the message listener for the MessageConsumer:

    listener = new TextListener();consumer.setMessageListener(listener);
  6. Starts the connection, causing message delivery to begin.

  7. Listens for the messages published to the destination, stopping when the user types the character q or Q:

    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()); 
        }
    }
  8. Closes the connection, which automatically closes the session and MessageConsumer.

The message listener, asynchconsumer/src/java/TextListener.java, follows these steps:

  1. When a message arrives, the onMessage method is called automatically.

  2. The onMessage method converts the incoming message to a TextMessage 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()); 
        }
    }

For this example, you will use the connection factory and destinations you created for A Simple Example of Synchronous Message Receives.

To Build and Package the AsynchConsumer Client Using NetBeans IDE

  1. From the File menu, choose Open Project.
  2. In the Open Project dialog, navigate to:
    tut-install/examples/jms/simple/
  3. Select the asynchconsumer folder.
  4. Select the Open as Main Project check box.
  5. Click Open Project.
  6. In the Projects tab, right-click the project and select Build.

To Deploy and Run the Clients for the Asynchronous Receive Example Using NetBeans IDE

  1. Run the AsynchConsumer example:
    1. Right-click the asynchconsumer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      topic
    4. Click OK.
    5. Right-click the project and select Run.

      The client displays the following lines and appears to hang:

      Destination type is topic
      To end program, type Q or q, then <return>
  2. Now run the Producer example:
    1. Right-click the producer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      topic 3
    4. Click OK.
    5. Right-click the project and select Run.

      The output of the client looks like this:

      Destination type is topic
      Sending message: This is message 1 from producer
      Sending message: This is message 2 from producer
      Sending message: This is message 3 from producer

      In the other tab, the AsynchConsumer client displays the following:

      Destination type is topic
      To end program, type Q or q, then <return>
      Reading message: This is message 1 from producer
      Reading message: This is message 2 from producer
      Reading message: This is message 3 from producer
      Message is not a TextMessage

      The last line appears because the client has received the non-text control message sent by the Producer client.

  3. Type Q or q in the Output window and press Return to stop the client.
  4. Now run the Producer client using a queue.

    In this case, as with the synchronous example, you can run the Producer client first, because there is no timing dependency between the sender and the receiver.

    1. Right-click the producer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      queue 3
    4. Click OK.
    5. Right-click the project and select Run.

      The output of the client looks like this:

      Destination type is queue
      Sending message: This is message 1 from producer
      Sending message: This is message 2 from producer
      Sending message: This is message 3 from producer
  5. Run the AsynchConsumer client.
    1. Right-click the asynchconsumer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      queue
    4. Click OK.
    5. Right-click the project and select Run.

      The output of the client looks like this:

      Destination type is queue
      To end program, type Q or q, then <return>
      Reading message: This is message 1 from producer
      Reading message: This is message 2 from producer
      Reading message: This is message 3 from producer
      Message is not a TextMessage
  6. Type Q or q in the Output window and press Return to stop the client.

To Build and Package the AsynchConsumer Client Using Ant

  1. In a terminal window, go to the asynchconsumer directory:
    cd ../asynchconsumer
  2. Type the following command:
    ant

    The targets package both the main class and the message listener class in the JAR file and place the file in the dist directory for the example.

To Deploy and Run the Clients for the Asynchronous Receive Example Using Ant and the appclient Command

  1. Deploy the client JAR file to the GlassFish Server, then retrieve the client stubs:
    ant getclient

    Ignore the message that states that the application is deployed at a URL.

  2. Run the AsynchConsumer client, specifying the topic destination type.
    appclient -client client-jar/asynchconsumerClient.jar topic

    The client displays the following lines (along with some additional output) and appears to hang:

    Destination type is topic
    To end program, type Q or q, then <return>
  3. In the terminal window where you ran the Producer client previously, run the client again, sending three messages.
    appclient -client client-jar/producerClient.jar topic 3

    The output of the client looks like this (along with some additional output):

    Destination type is topic
    Sending message: This is message 1 from producer
    Sending message: This is message 2 from producer
    Sending message: This is message 3 from producer

    In the other window, the AsynchConsumer client displays the following (along with some additional output):

    Destination type is topic
    To end program, type Q or q, then <return>
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer
    Message is not a TextMessage

    The last line appears because the client has received the non-text control message sent by the Producer client.

  4. Type Q or q and press Return to stop the client.
  5. Now run the clients using a queue.

    In this case, as with the synchronous example, you can run the Producer client first, because there is no timing dependency between the sender and receiver:

    appclient -client client-jar/producerClient.jar queue 3

    The output of the client looks like this:

    Destination type is queue
    Sending message: This is message 1 from producer
    Sending message: This is message 2 from producer
    Sending message: This is message 3 from producer
  6. Run the AsynchConsumer client:
    appclient -client client-jar/asynchconsumerClient.jar queue

    The output of the client looks like this (along with some additional output):

    Destination type is queue
    To end program, type Q or q, then <return>
    Reading message: This is message 1 from producer
    Reading message: This is message 2 from producer
    Reading message: This is message 3 from producer
    Message is not a TextMessage
  7. Type Q or q to stop the client.

A Simple Example of Browsing Messages in a Queue

This section describes an example that creates a QueueBrowser object to examine messages on a queue, as described in JMS Queue Browsers. This section then explains how to compile, package, and run the example using the GlassFish Server.

Writing the Client for the QueueBrowser Example

To create a QueueBrowser for a queue, you call the Session.createBrowser method with the queue as the argument. You obtain the messages in the queue as an Enumeration object. You can then iterate through the Enumeration object and display the contents of each message.

The messagebrowser/src/java/MessageBrowser.java client performs the following steps:

  1. Injects resources for a connection factory and a queue.

  2. Creates a Connection and a Session.

  3. Creates a QueueBrowser:

    QueueBrowser browser = session.createBrowser(queue);
  4. Retrieves the Enumeration that contains the messages:

    Enumeration msgs = browser.getEnumeration();
  5. Verifies that the Enumeration 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); 
        }
    }
  6. Closes the connection, which automatically closes the session and the QueueBrowser.

The format in which the message contents appear is implementation-specific. In the GlassFish Server, the message format looks something like this:

Message contents: 
Text: This is message 3 from producer
Class: com.sun.messaging.jmq.jmsclient.TextMessageImpl
getJMSMessageID(): ID:14-128.149.71.199(f9:86:a2:d5:46:9b)-40814-1255980521747
getJMSTimestamp(): 1129061034355
getJMSCorrelationID(): null
JMSReplyTo: null
JMSDestination: PhysicalQueue
getJMSDeliveryMode(): PERSISTENT
getJMSRedelivered(): false
getJMSType(): null
getJMSExpiration(): 0
getJMSPriority(): 4
Properties: null

For this example, you will use the connection factory and queue you created for A Simple Example of Synchronous Message Receives.

To Run the MessageBrowser Client Using NetBeans IDE

To build, package, deploy, and run the MessageBrowser example using NetBeans IDE, follow these steps.

You also need the Producer example to send the message to the queue, and one of the consumer clients to consume the messages after you inspect them. If you did not do so already, package these examples.

  1. From the File menu, choose Open Project.
  2. In the Open Project dialog, navigate to:
    tut-install/examples/jms/simple/
  3. Select the messagebrowser folder.
  4. Select the Open as Main Project check box.
  5. Click Open Project.
  6. In the Projects tab, right-click the project and select Build.
  7. Run the Producer client, sending one message to the queue:
    1. Right-click the producer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      queue
    4. Click OK.
    5. Right-click the project and select Run.

      The output of the client looks like this:

      Destination type is queue
      Sending message: This is message 1 from producer
  8. Run the MessageBrowser client. Right-click the messagebrowser project and select Run.

    The output of the client looks something like this:

    Message: 
    Text: This is message 1 from producer
    Class: com.sun.messaging.jmq.jmsclient.TextMessageImpl
    getJMSMessageID(): ID:12-128.149.71.199(8c:34:4a:1a:1b:b8)-40883-1255980521747
    getJMSTimestamp(): 1129062957611
    getJMSCorrelationID(): null
    JMSReplyTo: null
    JMSDestination: PhysicalQueue
    getJMSDeliveryMode(): PERSISTENT
    getJMSRedelivered(): false
    getJMSType(): null
    getJMSExpiration(): 0
    getJMSPriority(): 4
    Properties: null
    Message: 
    Class: com.sun.messaging.jmq.jmsclient.MessageImpl
    getJMSMessageID(): ID:13-128.149.71.199(8c:34:4a:1a:1b:b8)-40883-1255980521747
    getJMSTimestamp(): 1129062957616
    getJMSCorrelationID(): null
    JMSReplyTo: null
    JMSDestination: PhysicalQueue
    getJMSDeliveryMode(): PERSISTENT
    getJMSRedelivered(): false
    getJMSType(): null
    getJMSExpiration(): 0
    getJMSPriority(): 4
    Properties: null

    The first message is the TextMessage, and the second is the non-text control message.

  9. Run the SynchConsumer client to consume the messages.
    1. Right-click the synchconsumer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      queue
    4. Click OK.
    5. Right-click the project and select Run.

      The output of the client looks like this:

      Destination type is queue
      Reading message: This is message 1 from producer

To Run the MessageBrowser Client Using Ant and the appclient Command

To build, package, deploy, and run the MessageBrowser example using Ant, follow these steps.

You also need the Producer example to send the message to the queue, and one of the consumer clients to consume the messages after you inspect them. If you did not do so already, package these examples.

To run the clients, you need two terminal windows.

  1. In a terminal window, go to the messagebrowser directory.
    cd ../messagebrowser
  2. Type the following command:
    ant

    The targets place the application client JAR file in the dist directory for the example.

  3. In another terminal window, go to the producer directory.
  4. Run the Producer client, sending one message to the queue:
    appclient -client client-jar/producerClient.jar queue

    The output of the client looks like this (along with some additional output):

    Destination type is queue
    Sending message: This is message 1 from producer
  5. Go to the messagebrowser directory.
  6. Deploy the client JAR file to the GlassFish Server, then retrieve the client stubs:
    ant getclient

    Ignore the message that states that the application is deployed at a URL.

  7. Because this example takes no command-line arguments, you can run the MessageBrowser client using the following command:
    ant run

    Alternatively, you can type the following command:

    appclient -client client-jar/messagebrowserClient.jar

    The output of the client looks something like this (along with some additional output):

    Message: 
    Text: This is message 1 from producer
    Class: com.sun.messaging.jmq.jmsclient.TextMessageImpl
    getJMSMessageID(): ID:12-128.149.71.199(8c:34:4a:1a:1b:b8)-40883-1255980521747
    getJMSTimestamp(): 1255980521747
    getJMSCorrelationID(): null
    JMSReplyTo: null
    JMSDestination: PhysicalQueue
    getJMSDeliveryMode(): PERSISTENT
    getJMSRedelivered(): false
    getJMSType(): null
    getJMSExpiration(): 0
    getJMSPriority(): 4
    Properties: null
    Message: 
    Class: com.sun.messaging.jmq.jmsclient.MessageImpl
    getJMSMessageID(): ID:13-128.149.71.199(8c:34:4a:1a:1b:b8)-40883-1255980521767
    getJMSTimestamp(): 1255980521767
    getJMSCorrelationID(): null
    JMSReplyTo: null
    JMSDestination: PhysicalQueue
    getJMSDeliveryMode(): PERSISTENT
    getJMSRedelivered(): false
    getJMSType(): null
    getJMSExpiration(): 0
    getJMSPriority(): 4
    Properties: null

    The first message is the TextMessage, and the second is the non-text control message.

  8. Go to the synchconsumer directory.
  9. Run the SynchConsumer client to consume the messages:
    appclient -client client-jar/synchconsumerClient.jar queue

    The output of the client looks like this (along with some additional output):

    Destination type is queue
    Reading message: This is message 1 from producer

Running JMS Clients on Multiple Systems

JMS clients that use the GlassFish Server can exchange messages with each other when they are running on different systems in a network. The systems must be visible to each other by name (the UNIX host name or the Microsoft Windows computer name) and must both be running the GlassFish Server.


Note - Any mechanism for exchanging messages between systems is specific to the Java EE server implementation. This tutorial describes how to use the GlassFish Server for this purpose.


Suppose you want to run the Producer client on one system, earth, and the SynchConsumer client on another system, jupiter. Before you can do so, you need to perform these tasks:

  1. Create two new connection factories

  2. Change the name of the default JMS host on one system

  3. Edit the source code for the two examples

  4. Recompile and repackage the examples


    Note - A limitation in the JMS provider in the GlassFish 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 connection from a system that uses DHCP to a system that does not use DHCP. In the examples in this tutorial, earth can be a system that uses DHCP, and jupiter can be a system that does not use DHCP.


When you run the clients, they will work as shown in Figure 48-1. The client run on earth needs the queue on earth only so the resource injection will succeed. The connection, session, and message producer are all created on jupiter using the connection factory that points to jupiter. The messages sent from earth will be received on jupiter.

Figure 48-1 Sending Messages from One System to Another

Diagram showing a message being sent to a queue by a producer on Earth and being received by a consumer on Jupiter

For examples showing how to deploy more complex applications on two different systems, see An Application Example That Consumes Messages from a Remote Server and An Application Example That Deploys a Message-Driven Bean on Two Servers.

To Create Administered Objects for Multiple Systems

To run these clients, you must do the following:

  • Create a new connection factory on both earth and jupiter

  • Create a destination resource on both earth and jupiter

You do not have to install the tutorial examples on both systems, but you must be able to access the file system where it is installed. You may find it more convenient to install the tutorial examples on both systems if the two use different operating systems (for example, Windows and UNIX). Otherwise you will have to edit the tut-install/examples/bp-project/build.properties file and change the location of the javaee.home property each time you build or run a client on a different system.

  1. Start the GlassFish Server on earth.
  2. Start the GlassFish Server on jupiter.
  3. To create a new connection factory on jupiter, follow these steps:
    1. From a command shell on jupiter, go to the tut-install/examples/jms/simple/producer/ directory.
    2. Type the following command:
      ant create-local-factory

      The create-local-factory target, defined in the build.xml file for the Producer example, creates a connection factory named jms/JupiterConnectionFactory.

  4. To create a new connection factory on earth that points to the connection factory on jupiter, follow these steps:
    1. From a command shell on earth, go to the tut-install/examples/jms/simple/producer/ directory.
    2. Type the following command:
      ant create-remote-factory -Dsys=remote-system-name

      Replace remote-system-name with the actual name of the remote system.

      The create-remote-factory target, defined in the build.xml file for the Producer example, also creates a connection factory named jms/JupiterConnectionFactory. In addition, it sets the AddressList property for this factory to the name of the remote system.

    Additional resources will be created when you deploy the application, if they have not been created before.

    The reason the glassfish-resources.xml file does not specify jms/JupiterConnectionFactory is that on earth the connection factory requires the AddressList property setting, whereas on jupiter it does not. You can examine the targets in the build.xml file for details.

Changing the Default Host Name

By default, the default host name for the JMS service on the GlassFish Server is localhost. To access the JMS service from another system, however, you must change the host name. You can change it either to the actual host name or to 0.0.0.0.

You can change the default host name using either the Administration Console or the asadmin command.

To Change the Default Host Name Using the Administration Console

  1. On jupiter, start the Administration Console by opening a browser at http://localhost:4848/.
  2. In the navigation tree, expand the Configurations node, then expand the server-config node.
  3. Under the server-config node, expand the Java Message Service node.
  4. Under the Java Message Service node, expand the JMS Hosts node.
  5. Under the JMS Hosts node, select default_JMS_host.

    The Edit JMS Host page opens.

  6. In the Host field, type the name of the system, or type 0.0.0.0.
  7. Click Save.
  8. Restart the GlassFish Server.

To Change the Default Host Name Using the asadmin Command

  1. Specify a command like one of the following:
    asadmin set server-config.jms-service.jms-host.default_JMS_host.host="0.0.0.0"
    asadmin set server-config.jms-service.jms-host.default_JMS_host.host="hostname"
  2. Restart the GlassFish Server.

To Run the Clients Using NetBeans IDE

These steps assume you have the tutorial installed on both of the systems you are using and that you are able to access the file system of jupiter from earth or vice versa. You will edit the source files to specify the new connection factory. Then you will rebuild and run the clients.

  1. To edit the source files, follow these steps:
    1. On earth, open the following file in NetBeans IDE:
      tut-install/examples/jms/simple/producer/src/java/Producer.java
    2. Find the following line:
      @Resource(lookup = "jms/ConnectionFactory")
    3. Change the line to the following:
      @Resource(lookup = "jms/JupiterConnectionFactory")
    4. Save the file.
    5. On jupiter, open the following file in NetBeans IDE:
      tut-install/examples/jms/simple/synchconsumer/src/java/SynchConsumer.java
    6. Repeat Step b and Step c, then save the file.
  2. To recompile and repackage the Producer example on earth, right-click the producer project and select Clean and Build.
  3. To recompile and repackage the SynchConsumer example on jupiter, right-click the synchconsumer project and select Clean and Build.
  4. On earth, deploy and run Producer. Follow these steps:
    1. Right-click the producer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      queue 3
    4. Click OK.
    5. Right-click the project and select Run.

      The output looks like this (along with some additional output):

      Destination type is topic
      Sending message: This is message 1 from producer
      Sending message: This is message 2 from producer
      Sending message: This is message 3 from producer
  5. On jupiter, run SynchConsumer. Follow these steps:
    1. Right-click the synchconsumer project and select Properties.
    2. Select Run from the Categories tree.
    3. In the Arguments field, type the following:
      queue
    4. Click OK.
    5. Right-click the project and select Run.

      The output of the program looks like this (along with some additional output):

      Destination type is queue
      Reading message: This is message 1 from producer
      Reading message: This is message 2 from producer
      Reading message: This is message 3 from producer

To Run the Clients Using Ant and the appclient Command

These steps assume you have the tutorial installed on both of the systems you are using and that you are able to access the file system of jupiter from earth or vice versa. You will edit the source files to specify the new connection factory. Then you will rebuild and run the clients.

  1. To edit the source files, follow these steps:
    1. On earth, open the following file in a text editor:
      tut-install/examples/jms/simple/producer/src/java/Producer.java
    2. Find the following line:
      @Resource(lookup = "jms/ConnectionFactory")
    3. Change the line to the following:
      @Resource(lookup = "jms/JupiterConnectionFactory")
    4. Save and close the file.
    5. On jupiter, open the following file in a text editor:
      tut-install/examples/jms/simple/synchconsumer/src/java/SynchConsumer.java
    6. Repeat Step b and Step c, then save and close the file.
  2. To recompile and repackage the Producer example on earth, type the following:
    ant
  3. To recompile and repackage the SynchConsumer example on jupiter, go to the synchconsumer directory and type the following:
    ant
  4. On earth, deploy and run Producer. Follow these steps:
    1. On earth, from the producer directory, create any needed resources, deploy the client JAR file to the GlassFish Server, then retrieve the client stubs:
      ant getclient

      Ignore the message that states that the application is deployed at a URL.

    2. To run the client, type the following:
      appclient -client client-jar/producerClient.jar queue 3

      The output looks like this (along with some additional output):

      Destination type is topic
      Sending message: This is message 1 from producer
      Sending message: This is message 2 from producer
      Sending message: This is message 3 from producer
  5. On jupiter, run SynchConsumer. Follow these steps:
    1. From the synchconsumer directory, create any needed resources, deploy the client JAR file to the GlassFish Server, then retrieve the client stubs:
      ant getclient

      Ignore the message that states that the application is deployed at a URL.

    2. To run the client, type the following:
      appclient -client client-jar/synchconsumerClient.jar queue

      The output of the program looks like this (along with some additional output):

      Destination type is queue
      Reading message: This is message 1 from producer
      Reading message: This is message 2 from producer
      Reading message: This is message 3 from producer

Undeploying and Cleaning the Simple JMS Examples

After you finish running the examples, you can undeploy them and remove the build artifacts.

You can also use the asadmin delete-jms-resource command to delete the destinations and connection factories you created. However, it is recommended that you keep them, because they will be used in most of the examples later in this chapter. After you have created them, they will be available whenever you restart the GlassFish Server.