Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Developer's Guide

- Previous: Chapter 13 Using the Java Naming and Directory Interface
- Next: Chapter 15 Using the JavaMail API

# Chapter 14 Using the Java Message Service

This chapter describes how to use the JavaTM Message Service (JMS) API. The Sun Java System Application Server has a fully integrated JMS provider: the Sun Java System Message Queue software.

For general information about the JMS API, see the J2EE 1.4 Tutorial at `http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JMS.html#wp84181`.

For detailed information about JMS concepts and JMS support in the Application Server, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Administration Guide.

This chapter contains the following sections:

- The JMS Provider

- Message Queue Resource Adapter

- Administration of the JMS Service

- Restarting the JMS Client After JMS Configuration

- JMS Connection Features

- Load-Balanced Message Inflow

- Transactions and Non-Persistent Messages

- ConnectionFactory Authentication

- Message Queue varhome Directory

- Delivering SOAP Messages Using the JMS API

# The JMS Provider

The Application 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 Application Server uses the Sun Java System Message Queue software as its native JMS provider. The Message Queue software is tightly integrated into theApplication Server, providing transparent JMS messaging support. This support is known within Application Server as the JMS Service. The JMS Service requires only minimal administration.

The relationship of the Message Queue software to the Application Server can be one of these types: `LOCAL` or `REMOTE`. The results of these choices and their interactions with clustering are as follows:

- If the type is `LOCAL`, the Message Queue broker starts when the Application Server starts. This is the default for a stand-alone Application Server instance.

  To create a 1:1 relationship between Application Server instances and Message Queue brokers, set the type to `LOCAL` and give each Application Server instance a different default JMS host. You can do this regardless of whether clusters are defined in the Application Server or the Message Queue software.

- If the type is `REMOTE`, the Message Queue broker must be started separately. This is the default if clusters are defined in the Application Server. For information about starting the broker, see the Sun Java System Message Queue 3 2005Q4 Administration Guide.

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/app/docs/coll/1307.1`.

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

# Message Queue Resource Adapter

The Sun Java System Message Queue software is integrated into the Application Server using a resource adapter that is compliant with the Connector 1.5 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:

- Connection Factory: A connector connection pool with a `max-pool-size` of `250` and a corresponding connector resource.

- Destination (Topic or Queue): A connector administered object.

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

# Administration of the JMS Service

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

- Configuring the JMS Service

- The Default JMS Host

- Creating JMS Hosts

- Checking Whether the JMS Provider Is Running

- Creating Physical Destinations

- Creating JMS Resources: Destinations and Connection Factories

For more information about JMS administration tasks, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Administration Guide and the Sun Java System Message Queue 3 2005Q4 Administration Guide.

## Configuring the JMS Service

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

- To edit the JMS Service configuration using the Administration Console, open the Java Message Service component under the relevant configuration. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Administration Guide.

- To configure the JMS service, use the `asadmin set` command to set the following attributes:

      server.jms-service.init-timeout-in-seconds = 60
      server.jms-service.type = LOCAL
      server.jms-service.start-args =
      server.jms-service.default-jms-host = default_JMS_host
      server.jms-service.reconnect-interval-in-seconds = 60
      server.jms-service.reconnect-attempts = 3
      server.jms-service.reconnect-enabled = true
      server.jms-service.addresslist-behavior = random
      server.jms-service.addresslist-iterations = 3
      server.jms-service.mq-scheme = mq
      server.jms-service.mq-service = jms

  You can also set these properties:

      server.jms-service.property.instance-name = imqbroker
      server.jms-service.property.instance-name-suffix =
      server.jms-service.property.append-version = false

  You can use the `asadmin get` command to list all the JMS service attributes and properties. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Reference Manual.

You can override the JMS Service configuration using JMS connection factory settings. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Administration Guide.

Note –

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

## The Default JMS Host

A JMS host refers to a Sun Java System Message Queue broker. A default JMS host for the JMS service is provided, named `default_JMS_host`. This is the JMS host that the Application Server instance starts when the JMS Service type is configured as `LOCAL`.

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 Application 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:

- Use the Administration Console. Open the Java Message Service component under the relevant configuration, then select the JMS Hosts component. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Administration Guide.

- Use the `asadmin create-jms-host` command. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Reference Manual.

## Checking Whether the JMS Provider Is Running

You can use the `asadmin jms-ping` command to check whether a Sun Java System Message Queue instance is running. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 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 physical destination it listens to doesn’t exist, the Application Server automatically creates the physical destination and sets the value of the property `maxNumActiveConsumers` to `-1` (see Load-Balanced Message Inflow). However, it is good practice to create the physical destination beforehand.

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

- Use the Administration Console. Open the Resources component, open the JMS Resources component, then select Physical Destinations. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Administration Guide.

- Use the `asadmin create-jmsdest` command. This command acts on the default JMS host of its target. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 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 Application Server:

- Connection Factories: administered objects that implement the `ConnectionFactory`, `QueueConnectionFactory`, or `TopicConnectionFactory` interfaces.

- Destination Resources: administered objects that implement the `Queue` or `Topic` interfaces.

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

- To create a JMS resource using the Administration Console, open the Resources component, then open the JMS Resources component. Click Connection Factories to create a connection factory, or click Destination Resources to create a queue or topic. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Administration Guide.

- To create a JMS resource, use the `asadmin create-jms-resource` command. For details, see the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Reference Manual.

Note –

When a `Queue` is automatically created for a message-driven bean deployed to an Application Server cluster, the value of the property `maxNumActiveConsumers` is set to `-1` so that multiple consumers can access the `Queue` at the same time. For more information, see Load-Balanced Message Inflow.

All JMS resource properties that used to work with version 7 of the Application 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 Application Server. Further changes to the configuration are not available to the client JVM until the client is restarted.

# JMS Connection Features

The Sun Java System Message Queue software supports the following JMS connection features:

- Connection Pooling

- Connection Failover

Both these features use the `AddressList` configuration, which is populated with the hosts and ports of the JMS hosts defined in the Application 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 Sun Java System Message Queue software, the `AddressList` property is called `imqAddressList`.

## Connection Pooling

The Application 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 (see Deploying and Configuring a Stand-Alone Connector Module).

To use the command line, use the `asadmin create-connector-connection-pool` command to manage the pool (see Deploying and Configuring a Stand-Alone Connector Module.

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`.

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 Application Server.

## Connection Failover

To specify whether the Application 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 Application 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 the Sun Java System Application Server Enterprise Edition 8.1 2005Q2 Administration Guide.

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

# Load-Balanced Message Inflow

You can configure `ActivationSpec` properties of the `jmsra` resource adapter in the `sun-ejb-jar.xml` file for a message-driven bean using activation-config-property elements. Whenever a message-driven bean (`EndPointFactory`) is deployed, the connector runtime engine finds these properties and configures them accordingly in the resource adapter.

The Application Server transparently enables messages to be delivered in random fashion to message-driven beans having same `ClientID`. The `ClientID` is required for durable subscribers.

For nondurable subscribers in which the `ClientID` is not configured, all instances of a specific message-driven bean that subscribe to same topic are considered equal. When a message-driven bean is deployed to multiple instances of the Application Server, only one of the message-driven beans receives the message. If multiple distinct message-driven beans subscribe to same topic, one instance of each message-driven bean receives a copy of the message.

To support multiple consumers using the same queue, set the `maxNumActiveConsumers` property of the physical destination to a large value. If this property is set, the Sun Java System Message Queue software allows multiple message-driven beans to consume messages from same queue. The message is delivered randomly to the message-driven beans. If `maxNumActiveConsumers` is set to `-1`, there is no limit to the number of consumers.

The following sample application demonstrates load-balanced message inflow:

    install-dir/samples/ee-samples/failover/apps/mqfailover

# 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.

# ConnectionFactory Authentication

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 Application Server searches the container for authentication information before using the supplied user and password. Version 7 of the Application Server threw an exception in this situation.

# Message Queue varhome Directory

The Sun Java System Message Queue software uses a default directory for storing data such as persistent messages and its log file. This directory is called `varhome`. The Application Server uses domain-dir`/imq` as the `varhome` directory if the type of relationship between the Application 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 Application 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/app/docs/coll/1343.3`.

# 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:

- To send SOAP messages using the JMS API

- To receive SOAP messages using the JMS API

## To 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 Sun Java System 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();

## To 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.

- Previous: Chapter 13 Using the Java Naming and Directory Interface
- Next: Chapter 15 Using the JavaMail API

- © 2010, Oracle Corporation and/or its affiliates