Typically, a connection factory is created for you by a Message Queue administrator and preconfigured, using the administration tools described in the Chapter 1, Administrative Tasks and Tools, in Sun Java System Message Queue 4.3 Administration Guidewith whatever property settings are appropriate for connecting to particular JMS provider. The factory is then placed in a publicly available administered object store, where you can access it by name using the Java Naming and Directory Interface (JNDI) API. This arrangement has several benefits:
It allows the administrator to control the properties of client connections to the provider, ensuring that they are properly configured.
It enables the administrator to tune performance and improve throughput by adjusting configuration settings even after an application has been deployed.
By relying on the predefined connection factory to handle the configuration details, it helps keep client code provider-independent and thus more easily portable from one JMS provider to another.
Sometimes, however, it may be more convenient to dispense with JNDI lookup and simply create your own connection factory by direct instantiation. Although hard-coding configuration values for a particular JMS provider directly into your application code sacrifices flexibility and provider-independence, this approach might make sense in some circumstances: for example, in the early stages of application development and debugging, or in applications where reconfigurability and portability to other providers are not important concerns.
The following sections describe these two approaches to obtaining a connection factory: by JNDI lookup or direct instantiation.
Example 2–1 shows how to look up a connection factory object in the JNDI object store. The code example is explained in the procedure that follows.
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 connection factory object in the JNDI object store. String CF_LOOKUP_NAME = "MyConnectionFactory"; ConnectionFactory myFactory = (ConnectionFactory) ctx.lookup (CF_LOOKUP_NAME);
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 Using an LDAP User Repository in Sun Java System Message Queue 4.3 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 connection factory object in the administered object store and typecast it to the appropriate class:
String CF_LOOKUP_NAME = "MyConnectionFactory"; ConnectionFactory myFactory = (ConnectionFactory) ctx.lookup(CF_LOOKUP_NAME);
The lookup name you use, CF_LOOKUP_NAME, must match the name used when the object was stored.
You can now proceed to use the connection factory to create connections to the message broker, as described under Using Connections.
It is recommended that you use a connection factory just as you receive it from a JNDI lookup, with the property settings originally configured by your Message Queue administrator. However, there may be times when you need to override the preconfigured properties with different values of your own. You can do this from within your application code by calling the connection factory’s setProperty method. This method (inherited from the superclass AdministeredObject) takes two string arguments giving the name and value of the property to be set. The property names for the first argument are defined as static constants in the Message Queue class ConnectionConfiguration: for instance, the statement
sets the default password for establishing broker connections. See Connection Factory Attributes in Sun Java System Message Queue 4.3 Administration Guidefor complete information on the available connection factory configuration attributes.
java -DimqDefaultPassword=mellon MyMQClient
starts an application named MyMQClient with the same default password as in the preceding example. Setting a property value this way overrides any other value specified for it, whether preconfigured in the JNDI object store or set programmatically with the setProperty method.
A Message Queue administrator can prevent a connection factory’s properties from being overridden by specifying that the object be read-only when placing it in the object store. The properties of such a factory cannot be changed in any way, whether with the -D option from the command line or using the setProperty method from within your client application’s code. Any attempt to override the factory’s property values will simply be ignored.
Example 2–2 shows how to create a connection factory object by direct instantiation and configure its properties.
// Instantiate the connection factory object. com.sun.messaging.ConnectionFactory myFactory = new com.sun.messaging.ConnectionFactory(); // Set the connection factory’s configuration properties. myFactory.setProperty(ConnectionConfiguration.imqAddressList, "localhost:7676,broker2:5000,broker3:9999");
The following procedure explains each program satement in the previous code sample.
Instantiate the connection factory object.
The name ConnectionFactory is defined both as a JMS interface (in package javax.jms) and as a Message Queue class (in com.sun.messaging) that implements that interface. Since only a class can be instantiated, you must use the constructor defined in com.sun.messaging to create your connection factory object. Note, however, that you cannot import the name from both packages without causing a compilation error. Hence, if you have imported the entire package javax.jms.*, you must qualify the constructor with the full package name when instantiating the object:
com.sun.messaging.ConnectionFactory myFactory = new com.sun.messaging.ConnectionFactory();
Notice that the type declaration for the variable myFactory, to which the instantiated connection factory is assigned, is also qualified with the full package name. This is because the setProperty method, used in Instantiating a Connection Factory, belongs to the ConnectionFactory class defined in the package com.sun.messaging, rather than to the ConnectionFactory interface defined in javax.jms . Thus in order for the compiler to recognize this method, myFactory must be typed explicitly as com.sun.messaging.ConnectionFactory rather than simply ConnectionFactory (which would resolve to javax.jms.ConnectionFactory after importing javax.jms.* ).
The most important configuration property is imqAddressList, which specifies the host names and port numbers of the message brokers to which the factory creates connections. By default, the factory returned by the ConnectionFactory constructor in Instantiating a Connection Factory is configured to create connections to a broker on host localhost at port number 7676. If necessary, you can use the setProperty method, described in the preceding section, to change that setting:
Of course, you can also set any other configuration properties your application may require. See Connection Factory Attributes in Sun Java System Message Queue 4.3 Administration Guide for a list of the available connection factory attributes.
You can now proceed to use the connection factory to create connections to the message service, as described in the next section.