IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ

This article shows how to develop a J2SE Java™ application that sends and receives messages using IBM® WebSphere® MQ. The application uses the standard JMS and JNDI APIs from J2EE™, but does not require being deployed in a J2EE application server.

Bobby Woolf (bwoolf@us.ibm.com), WebSphere J2EE Consultant, IBM Software Services for WebSphere

Photo of Bobby WoolfBobby Woolf is a WebSphere J2EE Consultant for IBM Software Services for WebSphere (ISSW). Bobby assists clients in developing applications for WebSphere Application Server using WebSphere Studio Application Developer. He is a co-author of Enterprise Integration Patterns and The Design Patterns Smalltalk Companion. He also has a blog on the IBM developerWorks Web site called J2EE in Practice. Bobby is a frequent conference speaker.


developerWorks Master author
        level

23 February 2005

Introduction

J2EE applications that use Java Messaging Service (JMS) messaging are common, and there's plenty of documentation on how to make them work well. What is less well-documented is how to make a Java 2 Standard Edition (J2SE) application -- one without the benefits of an application server -- using a JMS messaging provider. This article shows how to make a standalone Java application work with WebSphere MQ as a JMS and JNDI client. Such an application can still take advantage of JMS asynchronous messaging without having to be deployed in a J2EE application server, such as IBM WebSphere Application Server.

An updated version of this article is available for WebSphere MQ V6.0.


Why a standalone application?

The first question one might ask is: Why configure a standalone application to use asynchronous messaging? J2SE is designed for developing simple applications that usually run in a single Java virtual machine (JVM) on one computer. The applications that generally use messaging are developed on the Java 2 Enterprise Edition (J2EE) platform, which provides a variety of services for enterprise applications, including messaging. Messaging is provided by JMS, which includes a standard API for accessing messaging systems. JMS applications also use the Java Naming and Directory Interface (JNDI) API to access the messaging system's managed resources, namely connection factories and destinations.

Even an application designed to run for a single user on the desktop may need to integrate with other applications and services. Such an application can benefit from using asynchronous messaging to do so, and, as a Java application, should use the JMS API (with JNDI) to perform messaging.

Standalone JMS

You may already have an application written that uses JMS and JNDI. This article includes a download file containing a simple example of JMS clients which run via main() methods. While this is hardly a useful application, it is adequate to demonstrate messaging. We will walk through how we modified the sample application to work with WebSphere MQ; you would make similar changes to your application.

The sample application works much like a J2EE program in that it uses JNDI to access managed resources (connection factories and destinations) from the JMS provider, and uses JMS to send and receive messages. (The application does not use message-driven beans because those are a type of Enterprise JavaBean™, and would require this application to be a J2EE application.)

The configuration shown in this article makes the following assumptions:

  • You are using WebSphere MQ V5.3 for Microsoft® Windows®. Versions for other platforms should work as well but have not been tested.
  • WebSphere MQ is installed on your local machine (which is referred to in the URLs as localhost).
  • Your WebSphere MQ installation has a queue manager named QMGR whose TCP listener is running on port 1414.

If your WebSphere MQ installation is different, you will need to modify these instructions and samples accordingly.


Developing point-to-point

First we will look at how to set up point-to-point messaging using queues. Configuring the application and the messaging system requires the following steps:

  1. Obtain and install support pacs for WebSphere MQ.
  2. Modify your application's JNDI code to use the support pacs.
  3. Modify the administration tool to use the support pacs.
  4. Configure WebSphere MQ with the necessary JMS resources.
  5. Create or modify an application execution script that uses the support pacs.
  6. Run the application.

Updated article available
An updated version of this article is available for WebSphere MQ V6.0.

The code modifications necessary are minimal, and in fact can be limited to modifying a jndi.properties file if your code uses one. The main change related to your code is to modify the script for running the code so that it has the necessary Java application resource (JAR) files on its classpath.

1. Obtain and install support pacs for WebSphere MQ

This example uses WebSphere MQ Version 5.3. Out of the box, this version does not provide everything you need to support a JMS program. It includes an implementation of the JMS interface, but not the JNDI interface. To add support for JNDI to WebSphere MQ, you need to install support pac ME01 (WebSphere MQ Initial Context), which in turn requires support pac MS0B (MQSeries Java classes for PCF). (See Resources.)

To install these support pacs, simply unzip them. Each contains a JAR file you'll need later. (The sample scripts assume you add the JAR files to the WebSphere MQ Java\lib directory.) Other than making sure you have the JAR files available and reading the accompanying documentation, there's no further installation to perform.

2. Modify your application's JNDI code to use the support pacs

In a J2EE application, using JNDI is pretty easy. You simply create an InitialContext (with no parameters) and start using it. This is because the J2EE container manages the JNDI contexts, including the one for the component (Web application or EJB class) that contains your code.

For a J2SE (standalone) application, there is no J2EE container managing the JNDI contexts, just a simpler J2SE container (basically a plain JVM). The component model is much simpler -- no Web applications, no EJBs -- so all code has the same JNDI context. Therefore, establishing an initial JNDI context requires more work in J2SE.

In J2EE, you can usually simply say:

Context context = new InitialContext();

with no parameters and get the JNDI context you need.

In J2SE, creating the initial context is a little more difficult. You need to use a different constructor, InitialContext(Hashtable), like this:

Properties env = new Properties();
// fill in the context properties
Context context = new InitialContext(env);

The context properties tell JNDI what context you want so that it can create the right one for you. In this case, we want one for accessing WebSphere MQ, namely the instance we have installed. To do so, we use code like this:

Properties env = new Properties();
env.put(
	Context.INITIAL_CONTEXT_FACTORY, 	
	"com.ibm.mq.jms.context.WMQInitialContextFactory");
env.put(Context.PROVIDER_URL, "localhost:1414/SYSTEM.DEF.SVRCONN");
Context context = new InitialContext(env);

This code sets a pair of context properties:

  • INITIAL_CONTEXT_FACTORY
    The name of the class JNDI we will use to create the InitialContext. Because we want to access WebSphere MQ through JNDI, the initial context factory we use is a WebSphere MQ class. (This class is provided by the ME01 support pac described above.)
  • PROVIDER_URL
    Specifies how to find our running WebSphere MQ installation. Much like the URL for an HTML file or a JDBC data source, the information in this URL tells JNDI how to find and access WebSphere MQ using the implementation provided by the support pac.

Your PROVIDER_URL may need to differ from the value shown here. If your WebSphere MQ install is on a different computer from the one you will run your client application on, you need to change localhost to the hostname or IP address of the WebSphere MQ machine. Likewise, port 1414 is the default listener port number for the first queue manager in WebSphere MQ. If your install's port number is different, or you want to use a different queue manager, you need to specify its port.

And that's it. That's all the code you need to change, the code for instantiating an initial JNDI context. From there, your code works the same. It uses JNDI to access the JMS connection factory and JMS queue, and uses them to send and receive messages. You can even store these JNDI context properties in a properties file (the standard name is jndi.properties) and then modify them without having to change (and recompile and re-JAR) any code at all.

3. Modify the administration tool to use the support pacs

The JMS administration tool for WebSphere MQ is called JMSAdmin.bat, located in the Java\bin directory of the MQ install directory. It needs to be modified to use the MS0B and ME01 support pacs.

Modify the script's classpath to add the support pacs' com.ibm.mq.pcf.jar and mqcontext.jar JAR files, something like this (if the JAR files were in the bin directory, which isn't really a good place):

set CLASSPATH=%CLASSPATH%;mqcontext.jar;com.ibm.mq.pcf.jar

The script will use the new classpath when it runs the administration class, com.ibm.mq.jms.admin.JMSAdmin.

The JMS administration tool's configuration file, JMSAdmin.config, also needs to be modified. Add lines to the file (and comment out any corresponding lines) to make the following settings:

INITIAL_CONTEXT_FACTORY=com.ibm.mq.jms.context.WMQInitialContextFactory
PROVIDER_URL=localhost:1414/SYSTEM.DEF.SVRCONN

Again, the URL for your installation may be different. In any case, these values are the same as what you used in your application's JNDI code. (JMSAdmin is just another WebSphere MQ client, just like your application.)

4. Configure WebSphere MQ with the necessary JMS resources

The JMS administration tool runs interactively, but it is easier to have it process a script that can be edited and run repeatedly. The script's filename can be anything; by convention, the extension is .scp. In this example, the filename is sampleconfig.scp. The two lines of interest right now are these:

def qcf(SampleQCF) qmgr(QMGR) tran(client) chan(SYSTEM.DEF.SVRCONN) +
    host(localhost) port(1414)
def q(SampleQueue) qmgr(QMGR) qu(SAMPLE.QUEUE)

These two lines create a javax.jms.QueueConnectionFactory with the JNDI name SampleQCF and a javax.jms.Queue named SampleQueue. This script assumes the queue manager is named QMGR; modify the script if your queue manager is named differently. Like the PROVIDER_URL value used earlier, if your install is running on a different machine or your queue manager is running on a different port, you will need to modify these settings in your script.

Once the script is ready, you run it from a command line like this:

C:\WebSphere MQ\Java\bin> JMSAdmin -v < sampleconfig.scp

In the WebSphere MQ Explorer, you should now see a queue named SampleQueue in the Console Root\WebSphere MQ\Queue Managers\QMGR\Queues folder.

5. Create or modify an application execution script that uses the support pacs

The sample scripts for running the JMS clients require these items in the classpath:

  • JMS API:
    %MQ_JAVA_INSTALL_PATH%/lib/jms.jar
  • J2EE Connector API:
    %MQ_JAVA_INSTALL_PATH%/lib/connector.jar
  • WebSphere MQ client:
    %MQ_JAVA_INSTALL_PATH%/lib/com.ibm.mq.jar
  • WebSphere MQ JMS implementation:
    %MQ_JAVA_INSTALL_PATH%/lib/com.ibm.mqjms.jar
  • MS0B support pac JAR file:
    com.ibm.mq.pcf.jar
  • ME01 support pac JAR file:
    mqcontext.jar

As explained earlier, the application's JNDI code must set the INITIAL_CONTEXT_FACTORY and PROVIDER_URL values. If those settings are being read from a jndi.properties file, it will need to be in the application's classpath as well.

6. Run the application

Now we're ready to test the application. Open two command windows, one for the sender and one for the receiver. Go to the directory with the sample code, and run the sender and receiver. Then type in a message like, this is a test. You should see this in the sender window:

C:\standalonewmq> StandaloneSender
java -cp "standalonewmq.jar;. . ." com.ibm.examples.StandaloneSender
Sender started.
Enter a message: this is a test
Sent message <this is a test> with ID <ID:414d5120. . .20005001>
Enter a message:
Sender stopped.
C:\standalonewmq>

And this is what you should see in the receiver window:

C:\standalonewmq> StandaloneReceiver
java -cp " standalonewmq.jar;. . ." com.ibm.examples.StandaloneReceiver
Receiver started.
Received message <this is a test> with ID <ID:414d5120. . .20005001>
Receiver stopped.
C:\standalonewmq>

The result shows that a message containing this is a test with an ID ending in 20005001 was sent and received. The example works.


Developing publish/subscribe

The sample application also includes a publisher and subscriber for a topic. This publish/subscribe example assumes you have already done the setup for point-to-point messaging. The following additional steps are required:

  1. Obtain and install the publish/subscribe support pac for WebSphere MQ.
  2. Configure WebSphere MQ for publish/subscribe and start the broker.
  3. Configure WebSphere MQ with the necessary JMS resources.
  4. Create or modify an application execution script.
  5. Run the application.

We already performed the other steps when we setup WebSphere MQ for the point-to-point part of the example.

1. Obtain and install the publish/subscribe support pac for WebSphere MQ

WebSphere MQ V5.3 does not include support for publish/subscribe. For that, you need to add support pac MA0C (WebSphere MQ (MQSeries) - Publish/Subscribe).

Supporting publish/subscribe

Other IBM products, including WebSphere Business Integration Event Broker and WebSphere Business Integration Message Broker, support publish/subscribe implemented not only with WebSphere MQ, but also with other implementations, such as IP multicast. Those products are beyond the scope of this article.

The latest fix packs for WebSphere MQ V5.3 (such as Fix Pack 8, CSD08) include MA0C, so if you already have a recent fix pack installed, you can skip installing MA0C. If you're not sure whether or not you have the support pac installed, go ahead and try to install it. If it is already installed, the installer will simply tell you so and then automatically exit.

To install the support pac, download it (see Resources), run it, and follow the instructions in the wizard.

2. Configure WebSphere MQ for publish/subscribe and start the broker

Once you have the publish/subscribe support pac installed, you need to configure and start it. At this point, if you were to try running the publisher or subscriber (go ahead and try, if you like), you would get this error:

javax.jms.JMSException: MQJMS5087: Unexpected error 2085 
accessing internal queue SYSTEM.JMS.REPORT.QUEUE

This error indicates that the internal queues WebSphere MQ requires to support JMS publish/subscribe have not been created. To create these queues, run the program runmqsc in the WebSphere MQ bin directory (not the Java\bin directory) with the configuration file MQJMS_PSQ.mqsc on the appropriate queue manager (again, assuming your queue manager is named QMGR). When you run the command, you should see output like this:

C:\WebSphere MQ\bin> runmqsc QMGR < MQJMS_PSQ.mqsc
. . .
8 MQSC commands read.
No commands have a syntax error.
All valid MQSC commands were processed.

Make sure the queue manager's publish/subscribe broker is running. To check, run the dspmqbrk command. It's probably not running, so the output looks like this:

C:\WebSphere MQ\bin> dspmqbrk -m QMGR
MQSeries Publish/Subscribe broker for queue manager QMGR not active

To start it, run the command strmqbrk:

C:\WebSphere MQ\bin> strmqbrk -m QMGR
MQSeries Publish/Subscribe broker started for queue manager QMGR.

If you run dspmqbrk again, this time it should say that the broker is running. (You can stop it later by running endmqbrk -m QMGR.)

3. Configure WebSphere MQ with the necessary JMS resources

We now need to configure WebSphere MQ with a topic connection factory and a topic. If you already ran the sampleconfig.scp earlier:

C:\WebSphere MQ\Java\bin> JMSAdmin -v < sampleconfig.scp

then you have already created these resources and don't need to run it again. But let's take a look at what this part of the script is doing. The two relevant lines from the configuration script are these (again, assuming your queue manager is named QMGR):

def tcf(SampleTCF) qmgr(QMGR)
def t(SampleTopic) topic(sampletopic)

The first line creates a javax.jms.TopicConnectionFactory registered in JNDI under the name SampleTCF. The second line creates a javax.jms.Topic named SampleTopic.

4. Create or modify an application execution script

The sample scripts for running the JMS clients must have the classpath items listed for point-to-point. In addition, the publish/subscribe support uses XA (that is, distributed transactions), so the scripts also need this item in the classpath:

  • the JTA API:
    %MQ_JAVA_INSTALL_PATH%/lib/jta.jar

5. Run the application

We are now ready to test publishing. Open three command windows, one for the publisher and two for two subscribers. Go to the directory with the sample code, and run the publisher and subscribers. Then type in a message, like broadcast this and you should see this in the publisher window:

C:\standalonewmq> StandalonePublisher
java -cp "standalonewmq.jar;. . ." com.ibm.examples.StandalonePublisher
Publisher started.
Enter a message: broadcast this
Published message <broadcast this> with ID <ID:414d5120. . .20005b02>
Enter a message:
Publisher stopped.
C:\standalonewmq>

You should see this in one subscriber window:

C:\standalonewmq> StandaloneSubscriber
java -cp "standalonewmq.jar;. . ." com.ibm.examples.StandaloneSubscriber
Subscriber started.
Received message <broadcast this> with ID <ID:414d5120. . .20002406>
Subscriber stopped.
C:\standalonewmq>

And this in the other subscriber window:

C:\standalonewmq> StandaloneSubscriber
java -cp "standalonewmq.jar;. . ." com.ibm.examples.StandaloneSubscriber
Subscriber started.
Received message <broadcast this> with ID <ID:414d5120. . .20002407>
Subscriber stopped.
C:\standalonewmq>

The single published message was sent to both subscribers. Each subscriber's message has a different ID because each subscriber gets its own copy of the message.


Conclusion

In this article, we've seen how a J2SE application can use WebSphere MQ using JMS and JNDI, without needing to be deployed in a J2EE container (such as WebSphere Application Server). We have seen:

  • How to get the proper JNDI initial context.
  • How to set the classpath appropriately using the JAR files included with WebSphere MQ.
  • What support pacs you need and how to use them.
  • How to configure WebSphere MQ.
  • How to administer WebSphere MQ resources so that they can be accessed as JMS resources using JNDI.

You are now prepared to convert your existing applications and develop new ones.


Download

DescriptionNameSize
Code sampleStandaloneWMQCode.zip  ( HTTP | FTP )16 KB

Resources

IBM products

IBM support

Java specifications

Other resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=48572
ArticleTitle=IBM WebSphere Developer Technical Journal: Developing a standalone Java application for WebSphere MQ
publish-date=02232005