Oracle GlassFish Server 3.0.1 Application Development Guide

Chapter 17 Using the Java Message Service

This chapter describes how to use the JavaTM Message Service (JMS) API. The Oracle GlassFishTM Server has a fully integrated JMS provider: the GlassFish Message Queue software.


Note –

JMS resources are supported only in the full GlassFish Server, not in the Web Profile.


For detailed information about JMS concepts and JMS support in the GlassFish Server, see Chapter 19, Administering the Java Message Service (JMS) , in Oracle GlassFish Server 3.0.1 Administration Guide.

For more information about Message Queue software, see the Oracle GlassFish Message Queue 4.4.2 Administration Guide.

This chapter contains the following sections:

The JMS Provider

The GlassFish Server support for JMS messaging, in general, and for message-driven beans, in particular, requires messaging middleware that implements the JMS specification: a JMS provider. The GlassFish Server uses the GlassFish Message Queue software as its native JMS provider. The Message Queue software is tightly integrated into theGlassFish Server, providing transparent JMS messaging support. This support is known within GlassFish Server as the JMS Service. The JMS Service requires only minimal administration.

The relationship of the Message Queue software to the GlassFish Server can be one of these types: EMBEDDED, LOCAL, or REMOTE. The effects of these choices on the Message Queue broker life cycle are as follows:

For more information about setting the type and the default JMS host, see Configuring the JMS Service.

For more information about the Message Queue software, refer to the documentation at http://docs.sun.com/coll/1343.13.

For general information about the JMS API, see the JMS web page at http://java.sun.com/products/jms/index.jsp.

Message Queue Resource Adapter

The Message Queue software is integrated into the GlassFish Server using a resource adapter that is compliant with the Connector specification. The module name of this system resource adapter is jmsra. Every JMS resource is converted to a corresponding connector resource of this resource adapter as follows:

You use connector configuration tools to manage JMS resources. For more information, see Chapter 12, Developing Connectors.

Generic Resource Adapter

The GlassFish Server provides a generic resource adapter for JMS, for those who want to use a JMS provider other than Message Queue. For details, see https://genericjmsra.dev.java.net/ and Configuring Resource Adapters for JMS in Oracle GlassFish Server 3.0.1 Administration Guide.

Administration of the JMS Service

To configure the JMS Service and prepare JMS resources for use in applications deployed to the GlassFish Server, you must perform these tasks:

For more information about JMS administration tasks, see Chapter 19, Administering the Java Message Service (JMS) , in Oracle GlassFish Server 3.0.1 Administration Guide and the Oracle GlassFish Message Queue 4.4.2 Administration Guide.

Configuring the JMS Service

The JMS Service configuration is available to all inbound and outbound connections pertaining to the GlassFish Server instance. You can edit the JMS Service configuration in the following ways:

You can override the JMS Service configuration using JMS connection factory settings. For details, see Chapter 19, Administering the Java Message Service (JMS) , in Oracle GlassFish Server 3.0.1 Administration Guide.


Note –

The GlassFish Server instance must be restarted after configuration of the JMS Service.


The Default JMS Host

A JMS host refers to a Message Queue broker. A default JMS host for the JMS service is provided, named default_JMS_host. This is the JMS host that the GlassFish Server uses for performing all Message Queue broker administrative operations, such as creating and deleting JMS destinations.

If you have created a multi-broker cluster in the Message Queue software, delete the default JMS host, then add the Message Queue cluster’s brokers as JMS hosts. In this case, the default JMS host becomes the first JMS host in the AddressList. For more information about the AddressList, see JMS Connection Features. You can also explicitly set the default JMS host; see Configuring the JMS Service.

When the GlassFish Server uses a Message Queue cluster, it executes Message Queue specific commands on the default JMS host. For example, when a physical destination is created for a Message Queue cluster of three brokers, the command to create the physical destination is executed on the default JMS host, but the physical destination is used by all three brokers in the cluster.

Creating JMS Hosts

You can create additional JMS hosts in the following ways:

For machines having more than one host, use the Host field in the Administration Console or the ---–mqhost option of create-jms-host to specify the address to which the broker binds.

Checking Whether the JMS Provider Is Running

You can use the asadmin jms-ping command to check whether a Message Queue instance is running. For details, see the Oracle GlassFish Server 3.0.1 Reference Manual.

Creating Physical Destinations

Produced messages are delivered for routing and subsequent delivery to consumers using physical destinations in the JMS provider. A physical destination is identified and encapsulated by an administered object (a Topic or Queue destination resource) that an application component uses to specify the destination of messages it is producing and the source of messages it is consuming.

If a message-driven bean is deployed and the Queue physical destination it listens to doesn’t exist, the GlassFish Server automatically creates the physical destination. However, it is good practice to create the Queue physical destination beforehand.

You can create a JMS physical destination in the following ways:

To purge all messages currently queued at a physical destination, use the asadmin flush-jmsdest command. This deletes the messages before they reach any message consumers. For details, see the Oracle GlassFish Server 3.0.1 Reference Manual.

To create a destination resource, see Creating JMS Resources: Destinations and Connection Factories.

Creating JMS Resources: Destinations and Connection Factories

You can create two kinds of JMS resources in the GlassFish Server:

In either case, the steps for creating a JMS resource are the same. You can create a JMS resource in the following ways:


Note –

All JMS resource properties that used to work with version 7 of the GlassFish Server are supported for backward compatibility.


Restarting the JMS Client After JMS Configuration

When a JMS client accesses a JMS administered object for the first time, the client JVM retrieves the JMS service configuration from the GlassFish Server. Further changes to the configuration are not available to the client JVM until the client is restarted.

JMS Connection Features

The Message Queue software supports the following JMS connection features:

Both these features use the AddressList configuration, which is populated with the hosts and ports of the JMS hosts defined in the GlassFish Server. The AddressList is updated whenever a JMS host configuration changes. The AddressList is inherited by any JMS resource when it is created and by any MDB when it is deployed.


Note –

In the Message Queue software, the AddressList property is called imqAddressList.


Connection Pooling

The GlassFish Server pools JMS connections automatically.

To dynamically modify connection pool properties using the Administration Console, go to either the Connection Factories page (see Creating JMS Resources: Destinations and Connection Factories) or the Connector Connection Pools page.

To use the command line, use the asadmin create-connector-connection-pool command to manage the pool.

The addresslist-behavior JMS service attribute is set to random by default. This means that each ManagedConnection (physical connection) created from the ManagedConnectionFactory selects its primary broker in a random way from the AddressList.

The addresslist-behavior JMS service attribute can be set to priority. This means that the first broker in the AddressList is selected first.

When a JMS connection pool is created, there is one ManagedConnectionFactory instance associated with it. If you configure the AddressList as a ManagedConnectionFactory property, the AddressList configuration in the ManagedConnectionFactory takes precedence over the one defined in the GlassFish Server.

Connection Failover

To specify whether the GlassFish Server tries to reconnect to the primary broker if the connection is lost, set the reconnect-enabled attribute in the JMS service. To specify the number of retries and the time between retries, set the reconnect-attempts and reconnect-interval-in-seconds attributes, respectively.

If reconnection is enabled and the primary broker goes down, the GlassFish Server tries to reconnect to another broker in the AddressList. The AddressList is updated whenever a JMS host configuration changes. The logic for scanning is decided by two JMS service attributes, addresslist-behavior and addresslist-iterations.

You can override these settings using JMS connection factory settings. For details, see Chapter 19, Administering the Java Message Service (JMS) , in Oracle GlassFish Server 3.0.1 Administration Guide.

The Message Queue software transparently transfers the load to another broker when the failover occurs. JMS semantics are maintained during failover.

Transactions and Non-Persistent Messages

During transaction recovery, non-persistent messages might be lost. If the broker fails between the transaction manager’s prepare and commit operations, any non-persistent message in the transaction is lost and cannot be delivered. A message that is not saved to a persistent store is not available for transaction recovery.

Using the ConfigurableTransactionSupport Interface

The Java EE Connector 1.6 specification allows a resource adapter to use the transaction-support attribute to specify the level of transaction support that the resource adapter handles. However, the resource adapter vendor does not have a mechanism to figure out the current transactional context in which a ManagedConnectionFactory is used.

If a ManagedConnectionFactory implements an optional interface called com.sun.appserv.connectors.spi.ConfigurableTransactionSupport, the GlassFish Server notifies the ManagedConnectionFactory of the transaction-support configured for the connector connection pool when the ManagedConnectionFactory instance is created for the pool. Connections obtained from the pool can then be used with a transaction level at or lower than the configured value. For example, a connection obtained from a pool that is set to XA_TRANSACTION could be used as a LOCAL resource in a last-agent-optimized transaction or in a non-transactional context.

Authentication With ConnectionFactory

If your web, EJB, or client module has res-auth set to Container, but you use the ConnectionFactory.createConnection("user","password") method to get a connection, the GlassFish Server searches the container for authentication information before using the supplied user and password. Version 7 of the GlassFish Server threw an exception in this situation.

Message Queue varhome Directory

The Message Queue software uses a default directory for storing data such as persistent messages and its log file. This directory is called varhome. The GlassFish Server uses domain-dir/imq as the varhome directory if the type of relationship between the GlassFish Server and the Message Queue software is LOCAL or EMBEDDED. If the relationship type is REMOTE, the Message Queue software determines the varhome location. For more information about the types of relationships between the GlassFish Server and Message Queue, see The JMS Provider.

When executing Message Queue scripts such as as-install/imq/bin/imqusermgr, use the -varhome option to point the scripts to the Message Queue data if the relationship type is LOCAL or EMBEDDED. For example:

imqusermgr -varhome $AS_INSTALL/domains/domain1/imq add -u testuser

For more information about the Message Queue software, refer to the documentation at http://docs.sun.com/coll/1343.13.

Delivering SOAP Messages Using the JMS API

Web service clients use the Simple Object Access Protocol (SOAP) to communicate with web services. SOAP uses a combination of XML-based data structuring and Hyper Text Transfer Protocol (HTTP) to define a standardized way of invoking methods in objects distributed in diverse operating environments across the Internet.

For more information about SOAP, see the Apache SOAP web site at http://xml.apache.org/soap/index.html.

You can take advantage of the JMS provider’s reliable messaging when delivering SOAP messages. You can convert a SOAP message into a JMS message, send the JMS message, then convert the JMS message back into a SOAP message. The following sections explain how to do these conversions:

ProcedureTo Send SOAP Messages Using the JMS API

  1. Import the MessageTransformer library.

    import com.sun.messaging.xml.MessageTransformer;

    This is the utility whose methods you use to convert SOAP messages to JMS messages and the reverse. You can then send a JMS message containing a SOAP payload as if it were a normal JMS message.

  2. Initialize the TopicConnectionFactory, TopicConnection, TopicSession, and publisher.

    tcf = new TopicConnectionFactory();
    tc = tcf.createTopicConnection();
    session = tc.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);
    topic = session.createTopic(topicName);
    publisher = session.createPublisher(topic);
  3. Construct a SOAP message using the SOAP with Attachments API for Java (SAAJ).

    /*construct a default soap MessageFactory */
    MessageFactory mf = MessageFactory.newInstance();
    * Create a SOAP message object.*/
    SOAPMessage soapMessage = mf.createMessage();
    /** Get SOAP part.*/
    SOAPPart soapPart = soapMessage.getSOAPPart();
    /* Get SOAP envelope. */
    SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
    /* Get SOAP body.*/
    SOAPBody soapBody = soapEnvelope.getBody();
    /* Create a name object. with name space */
    /* http://www.sun.com/imq. */
    Name name = soapEnvelope.createName("HelloWorld", "hw",
     "http://www.sun.com/imq");
    * Add child element with the above name. */
    SOAPElement element = soapBody.addChildElement(name)
    /* Add another child element.*/
    element.addTextNode( "Welcome to GlassFish Web Services." );
    /* Create an atachment with activation API.*/
    URL url = new URL ("http://java.sun.com/webservices/");
    DataHandler dh = new DataHandler (url);
    AttachmentPart ap = soapMessage.createAttachmentPart(dh);
    /*set content type/ID. */
    ap.setContentType("text/html");
    ap.setContentId("cid-001");
    /**  add the attachment to the SOAP message.*/
    soapMessage.addAttachmentPart(ap);
    soapMessage.saveChanges();
  4. Convert the SOAP message to a JMS message by calling the MessageTransformer.SOAPMessageintoJMSMessage() method.

    Message m = MessageTransformer.SOAPMessageIntoJMSMessage (soapMessage, 
    session );
  5. Publish the JMS message.

    publisher.publish(m);
  6. Close the JMS connection.

    tc.close();

ProcedureTo Receive SOAP Messages Using the JMS API

  1. Import the MessageTransformer library.

    import com.sun.messaging.xml.MessageTransformer;

    This is the utility whose methods you use to convert SOAP messages to JMS messages and the reverse. The JMS message containing the SOAP payload is received as if it were a normal JMS message.

  2. Initialize the TopicConnectionFactory, TopicConnection, TopicSession, TopicSubscriber, and Topic.

    messageFactory = MessageFactory.newInstance();
    tcf = new com.sun.messaging.TopicConnectionFactory();
    tc = tcf.createTopicConnection();
    session = tc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
    topic = session.createTopic(topicName);
    subscriber = session.createSubscriber(topic);
    subscriber.setMessageListener(this);
    tc.start();
  3. Use the OnMessage method to receive the message. Use the SOAPMessageFromJMSMessage method to convert the JMS message to a SOAP message.

    public void onMessage (Message message) {
    SOAPMessage soapMessage =
     MessageTransformer.SOAPMessageFromJMSMessage( message,
     messageFactory ); }
  4. Retrieve the content of the SOAP message.