All Message Queue messages travel from a message producer to a message consumer by way of a destination on a message broker. Message delivery is thus a two-stage process: the message is first delivered from the producer to the destination and later from the destination to the consumer. Physical destinations on the broker are created administratively by a Message Queue administrator, using the administration tools described in Chapter 6, Managing Physical Destinations, in Sun Java System Message Queue 3.7 UR1 Administration Guide. The broker provides routing and delivery services for messages sent to such a destination.
As described earlier under Messaging Domains, Message Queue supports two types of destination, depending on the messaging domain being used:
These two types of destination are represented by the Message Queue classes Queue and Topic, respectively. These, in turn, are both subclasses of the generic class Destination, part of the unified messaging domain that subsumes both the point-to-point and publish-subscribe domains. A client program that uses the Destination superclass can thus handle both queue and topic destinations indiscriminately.
Because JMS providers differ in their destination addressing conventions, Message Queue does not define a standard address syntax for obtaining access to a destination. Rather, the destination is typically placed in a publicly available administered object store by a Message Queue administrator and accessed by the client using a JNDI lookup in a manner similar to that described earlier for connection factories (see Looking Up a Connection Factory With JNDI).
Example 2–3 shows how to look up a destination object in the JNDI object store.
If a Message Queue client is a J2EE component, JNDI resources are provided by the J2EE container. In such cases, JNDI lookup code may differ from that shown here; see your J2EE provider documentation for details.
// Create the environment for constructing the initial JNDI naming context. Hashtable env = new Hashtable(); // Store the environment attributes that tell JNDI which initial // context factory to use and where to find the provider. env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); env.put(Context.PROVIDER_URL, "file:///C:/imq_admin_objects"); // Create the initial context. Context ctx = new InitialContext(env); // Look up the destination object in the JNDI object store. String DEST_LOOKUP_NAME = "MyDest"; Destination MyDest = (Destination) ctx.lookup(DEST_LOOKUP_NAME);
The following section explains the program statements in Example 2–3.
Create the environment for constructing the initial JNDI naming context.
How you create the initial context depends on whether you are using a file-system object store or a Lightweight Directory Access Protocol (LDAP) server for your Message Queue administered objects. The code shown here assumes a file-system store; for information about the corresponding LDAP object store attributes, see Chapter 8, Managing Administered Objects, in Sun Java System Message Queue 3.7 UR1 Administration Guide.
Hashtable env = new Hashtable();
You can also set an environment by specifying system properties on the command line, rather than programmatically. For instructions, see the README file in the JMS example applications directory.
The names of these attributes are defined as static constants in class Context:
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); env.put(Context.PROVIDER_URL, "file:///C:/imq_admin_objects");
The directory represented by C:/imq_admin_objects must already exist; if necessary, you must create the directory before referencing it in your code.
Context ctx = new InitialContext(env);
If you use system properties to set the environment, omit the environment parameter when creating the context:
Context ctx = new InitialContext();
Look up the destination object in the administered object store and typecast it to the appropriate class:
String DEST_LOOKUP_NAME = "MyDest"; Destination MyDest = (Destination) ctx.lookup(DEST_LOOKUP_NAME);
The lookup name you use, DEST_LOOKUP_NAME, must match the name used when the object was stored. Note that the actual destination object returned from the object store will always be either a (point-to-point) queue or a (publish/subscribe) topic, but that either can be assigned to a variable of the generic unified-domain class Destination.
As with connection factories, you may sometimes find it more convenient to dispense with JNDI lookup and simply create your own queue or topic destination objects by direct instantiation. Although a variable of type Destination can accept objects of either class, you cannot directly instantiate a Destination object; the object must always belong to one of the specific classes Queue or Topic. The constructors for both of these classes accept a string argument specifying the name of the physical destination to which the object corresponds:
Destination myDest = new com.sun.messaging.Queue("myDest");
Note, however, that this only creates a Java object representing the destination; it does not actually create a physical destination on the message broker. The physical destination itself must still be created by a Message Queue administrator, with the same name you pass to the constructor when instantiating the object.
Destination names beginning with the letters mq are reserved and should not be used by client programs.
Unlike connection factories, destinations have a much more limited set of configuration properties. In fact, only two such properties are defined in the Message Queue class DestinationConfiguration: the name of the physical destination itself (imqDestinationName) and an optional descriptive string (imqDestinationDescription). Since the latter property is rarely used and the physical destination name can be supplied directly as an argument to the Queue or Topic constructor as shown above, there normally is no need (as there often is with a connection factory) to specify additional properties with the object’s setProperty method. Hence the variable to which you assign the destination object (myDest in the example above) need not be typed with the Message Queue class com.sun.messaging.Destination; the standard JMS interface javax.jms.Destination (which the Message Queue class implements) is sufficient. If you have imported the full JMS package javax.jms.*, you can simply declare the variable with the unqualified name Destination, as above, rather than with something like
com.sun.messaging.Destination myDest = new com.sun.messaging.Queue("myDest");
as shown earlier for connection factories.
A temporary destination is one that exists only for the duration of the connection that created it. You may sometimes find it convenient to create such a destination to use, for example, as a reply destination for messages you send. Temporary destinations are created with the session method createTemporaryQueue or createTemporaryTopic (see Working With Sessions below): for example,
TemporaryQueue tempQueue = mySession.createTemporaryQueue();
Although the temporary destination is created by a particular session, its scope is actually the entire connection to which that session belongs. Any of the connection’s sessions (not just the one that created the temporary destination) can create a message consumer for the destination and receive messages from it. The temporary destination is automatically deleted when its connection is closed, or you can delete it explicitly by calling its delete method: