Running a standalone Java application on WebSphere MQ V6.0
The article Developing a standalone Java application for WebSphere MQ showed how to use IBM WebSphere MQ V5.3 as a Java™ Messaging Service (JMS) and Java Naming and Directory Interface (JNDI) provider for a Java 2 Standard Edition (J2SE) application (more specifically, for an application that is not running in a Java 2 Enterprise Edition (J2EE) application server). This article revisits that same topic, but this time with attention to WebSphere MQ V6.0, which now includes as part of the base product the JMS classes needed to create JMS applications, as well as the innate ability to act as a publish/subscribe broker that implements JMS topics. The result is a platform for which it is simpler to develop applications, as well as quicker to deploy to, and easier to manage.
The sample code and configurations provided with this article have been overhauled with these changes in mind. Also included with this article are additional sections on the unified domain classes in JMS 1.1, exception handling, transport bindings, and other best practices. Even readers familiar with the first article will find this one to be full of additional, useful information.
Why a standalone JMS application?
Why, one might wonder, would you want to write a JMS messaging program to operate outside of a J2EE environment? True, J2EE has received much of the messaging spotlight, but messaging was around before J2EE and we still need to do many of the same tasks we used messaging for then -- tasks for which the J2EE environment may be overqualified, or just simply inappropriate. These include batch jobs, bridges, conversions, utilities, administration, instrumentation, monitoring, and notification of real-world events, among other things. Coding outside of the J2EE environment, however, does not preclude the use of JMS. Given Java as the programming language of choice, and JMS the standard messaging API for Java, the question really is: Why wouldn't you want to use JMS to meet these messaging requirements?
Layers of a JMS application
A running JMS application contains three distinct layers of code, as shown in Figure 1:
- JMS application - Provider-independent; accesses the provider via JMS using JNDI.
- JMS implementation - Provider-specific JMS objects.
- Messaging provider - The messaging system itself, which in this case is WebSphere MQ.
Figure 1. Layers of a JMS application
As depicted in Figure 1, the application code does not access the messaging provider directly; rather, the access is accomplished by a provider-specific layer of code, in between whose individual objects are accessed via JNDI.
JMS hides most details of the JMS implementation and provider layers so that the Java developer can construct a JMS application that is mostly provider-neutral. However, the person who administers the JMS provider definitely needs to understand the JMS implementation layer, because configuration needs to take place here to make the application work with the provider. The JMS specification describes the programming API but leaves the details of implementation to the vendor. The standard JMS API hides the implementation details from the Java developer, but the JMS provider administrator must know the configuration details, and these configuration details differ for each vendor's product.
It is important to understand how the JMS application, JMS implementation, and messaging provider interact, so we will discuss them each in turn, starting with the provider.
The messaging provider transports messages reliably between processes, across network connections. It does not necessarily have to support JMS. For example, WebSphere MQ existed long before the JMS specification (it used to be called IBM MQSeries), and even today, many non-Java applications use WebSphere MQ without ever using JMS. Here, though, we assume the messaging provider is WebSphere MQ and that applications will access it through its optional JMS interface.
WebSphere MQ runs as one or more queue managers. Each queue manager is a set of processes that defines a set of queues, organizes messages within those queues, stores the messages in memory and on disk, and transports messages between messaging clients and other queue managers. WebSphere MQ implements point-to-point messaging using queues. A WebSphere MQ process known as the Publish/Subscribe Broker provides publish/subscribe functionality using native WebSphere MQ queues as its data store. WebSphere MQ uses these features to implement JMS queues and topics.
There is no JMS object that corresponds to a WebSphere MQ queue manager and no JMS API to programmatically perform administration and configuration tasks, like starting or stopping a queue manager, defining or deleting WebSphere MQ objects, or performing any other WebSphere MQ-specific administrative tasks. It is therefore necessary to know enough about basic WebSphere MQ administration to make sure the queue manager is running and that it is configured with the resources expected by a JMS application. In your environment, this may be performed by the WebSphere MQ Administrator.
If you are interested in the pub/sub messaging domain, it is important to note that in WebSphere MQ, the publish/subscribe broker does not start automatically when the queue manager starts. After starting the queue manager, the broker must also be started before applications can perform publish/subscribe messaging. Beginning with WebSphere MQ V6, the broker may be configured to start and stop under control of the queue manager.
Client mode vs. bindings mode
In WebSphere MQ, there are two ways for an application to connect to the WebSphere MQ queue manager. The two approaches are called bindings mode and client mode. It is important to understand the differences, advantages, and disadvantages of each mode:
Bindings mode is the native connection mode for WebSphere MQ. In bindings mode, a JMS application must run on the same host machine as the queue manager, and they will communicate using Inter-Process Communication (IPC) protocols.
In client mode, a JMS application establishes a network session with the queue manager's agent process, usually over TCP/IP. The agent then talks to the queue manager using bindings mode, performing API calls on behalf of the application.
There is no difference in the messaging client API between bindings mode and client mode. In JMS, all of the connection parameters for these modes are stored in the connection factory object and are not visible to the application. However, there are some significant operational considerations to be aware of:
All client mode API calls execute in three steps:
- The API call is transmitted from the client application to the agent.
- The agent executes the call on the queue manager.
- The results of the call are transmitted from the agent back to the client application.
If the network connection breaks during this exchange, the client application cannot determine whether the connection broke in the first step (before the API call was delivered to the agent process), or in the third step (when the results were to be transmitted back). Consequently, if the client mode connection is broken, the outcome of the last API call is undetermined. It is therefore recommended to use transacted sessions and code explicit commit() and rollback() method calls when client mode is (or might be) used. With this approach, the application may receive a duplicate message after a broken connection, but it will not lose any.
XA transactions are not available in client mode when using the base WebSphere MQ client. IBM offers an enhanced version called Extended Transactional Client which does provide XA capability over a client mode connection, but this is a separately licensed and priced product which should not be confused with the free WebSphere MQ base client.
Because the bindings mode connection uses shared memory, there is no overhead associated with transport over a network connection. Client mode performance can vary with network load, even to the point of breaking the connection. Firewalls and routers can also time out and disconnect a client session.
For the reasons outlined above, use bindings mode whenever possible. On the other hand, bindings mode requires that the queue manager be installed on the same host machine as the application (which isn't always possible); client mode enables an application to access a queue manager on a different host machine. That said, bindings mode is generally better, but client mode also has advantages. A good rule of thumb: A machine hosting a J2SE JMS application should have a queue manager installed (whenever possible) and the application should connect via bindings mode. The sample code includes connection factories for both client and bindings mode to demonstrate how to implement both.
There are a few WebSphere MQ configuration details required to accept a client mode connection. First, a listener process must be started. WebSphere MQ provides an executable called runmqlsr which, by default, listens on port 1414. Client mode also requires a SVRCONN channel definition on the queue manager. For the connection to work, the connection factory must include the channel name, listener port, and the host name or IP address of the queue manager's machine. The listener and channel configurations to run the sample code are provided in the next section.
It should also be noted that the best way to provide WebSphere MQ client functionality is to install the latest WebSphere MQ software package, in either the server version or the client version. It is possible to simply grab the Java JAR files from one installation and relocate them to the client machine and many people do. While the application will run this way, this arrangement does not install the many useful utilities and diagnostics provided in the full package. In particular, complete installation of the WebSphere MQ client facilitates the application of maintenance and patches, as well as the querying of the installed version. For the purposes of this article, it is assumed that the WebSphere MQ server is installed so we can create a queue manager locally, and that the option to also install client support was selected. (See Related topics to download a trial copy of WebSphere MQ to use for this example.)
Each provider implements the JMS API specific to the way the provider works. This provider-specific implementation enables the provider-independent code in a JMS program to attach to the specific JMS provider. Because this implementation is different for each provider, those who administer the JMS objects or the messaging provider must understand how to configure the implementation layer. Since the provider is WebSphere MQ in this case, the instructions provided here are WebSphere MQ-specific.
JMS administered objects
Administered objects are the root provider-specific objects that implement JMS interfaces and are directly accessible by the application. JMS applications use Java Naming and Directory Interface (JNDI) to retrieve the administered objects by name from a registry. The entries contain both public attributes, such as object type (queue or topic for instance), which are used by the JMS application, and private attributes, which are used by the provider's JMS implementation classes. While there are many types of resources that can be represented in a registry, three types of administered objects are of primary interest to JMS: connection factory, queue, and topic. A JMS application communicates with WebSphere MQ queue managers via these administered objects.
The connection factory enables the JMS program to open a connection with a queue manager to send and receive messages. Messages are then produced or consumed using queue or topic objects. There is a one-to-one correspondence between a JMS queue and the WebSphere MQ implementation of a queue; however, there is no WebSphere MQ object that corresponds directly to a JMS topic. WebSphere MQ implements topics with the publish/subscribe broker, which uses a broker control queue and a stream queue onto which messages are published. These run time details are part of WebSphere MQ's JMS implementation and are completely hidden from a JMS application. From an application's point of view, both the queue and topic implementations in WebSphere MQ are accessed as JMS administered objects via JNDI and behave exactly as described in the JMS specification.
Another important function of these provider-specific objects is to set and enforce administration policies or business requirements. For example, message priority can be specified in the application code but may also be overridden through settings in the administered objects. There are many other provider-specific object properties for queues, topics, and connection factories, and it is worthwhile to become familiar with them.
At first glance, these provider-specific objects may seem like yet another thing to learn and administer when all you want to do is run a simple piece of code. But the power of these provider-specific objects is that they decouple the code from the provider which, in turn, makes the remaining code environment-independent and portable. For example, it is common to have different names for queues in different environments (development, test, production, and so on), or for different releases of an application. Since the WebSphere MQ names are encapsulated within the JMS administered objects, the application code is not affected by these changes. In fact, most of the application code need never know whether the object represents a queue or a topic, or even which vendor's provider is being used. The provider-specific objects make all of these implementation details external to your code.
Administered object registry
The JMS administered objects must be registered in a directory that implements the JNDI API. JNDI enables a Java component to access a resource via a unique name without regard to where the resource is stored, how it is implemented, or how the container and its JNDI provider actually enable access to the resource. A resource can be any object that the program needs to access globally -- a Java Database Connectivity (JDBC) data source, an Enterprise JavaBeans (EJB) home, a J2EE Connector Architecture connector, and so on.
As delivered, WebSphere MQ provides JNDI support for three different types of directory service: a J2EE environment, such as WebSphere Application Server, LDAP, and a filesystem-based implementation. We will use the filesystem-based service because it does not require any additional software or hardware components beyond what is provided in the WebSphere MQ install. A JMS application requires at least one connection factory and at least one queue or topic. Next, we will examine how WebSphere MQ represents these as JNDI-accessible registry entries.
The connection factory provides all of the information that the application needs to connect to the WebSphere MQ queue manager. The application does not need to know whether it is connecting via client or bindings mode, nor the name of the queue manager. The application code just uses JNDI to look up the connection factory by name; the low-level details of accessing the queue manager and creating connections are handled by the WebSphere MQ-specific objects.
The connection factory implementation contains more than two dozen WebSphere MQ-specific properties. The default settings use the most conservative options and work fine for a simple program, such as the sample included with this article. However, to effectively administer JMS objects or WebSphere MQ, it is necessary to understand how the two interact.
As of JMS 1.1, JMS applications are not required to distinguish between queues and topics. In the application code, they are both just destinations which produce or consume messages. However, queues and topics are inherently different at the transport level and so the registry entry for any given destination must be specifically defined as either a queue or topic. When the JMS application performs a JNDI lookup of a destination, the correct object is located based on its name and the result returned can be either an instance of a queue or an instance of a topic. In most cases, the application can simply use the destination object without regard to whether it represents a queue or topic, and simply produce or consume messages as appropriate. If required, the
instanceof operator can be used to determine the specific destination subtype.
As with the connection factory, both the queue and topic registry entries have a number of WebSphere MQ-specific properties. Again, the defaults are sufficient for the simple demo application included with this article, but administrators should become familiar with all of the properties and their consequences before deploying a production application.
The top level of the JMS application stack is the JMS application itself. The application uses JNDI to lookup the various JMS administered objects it needs and uses these to attach to the WebSphere MQ messaging provider. The application need only know the JNDI names of the resources. These names must match exactly and are case sensitive.
From the JMS perspective, as mentioned earlier, one of the most prominent changes has been to combine point-to-point messaging and publish-subscribe into a single domain. While domain-specific classes such as Queue, Topic, QueueConnectionFactory and TopicConnectionFactory are still available, they have been superseded by neutral classes like Destination and ConnectionFactory, which are suitable for both queues and topics.
This unification of the queue and topic domains is significant and deserves a closer look. Under the older specification, the application code had to be written specifically for queues or topics because the classes themselves were domain-specific. Thus, changing from a queue to a topic involved recoding, recompiling, and redeploying the application. A more subtle but important implication is that you had to know whether the destination was a queue or a topic at design time. Under JMS 1.1, it is often not necessary to know until run time what kind of object the destination will be. This means the program may be coded knowing only the high level message flow.
The sample code provided with this article demonstrates the use of these unified domain classes. The example utilizes a queue and a topic on the queue manager, using the JNDI bindings to switch back and forth between them. Note that changing the JNDI bindings while the program is running will not dynamically switch the program between queues and topics. The changes become effective only when the object is looked up in JNDI, which typically occurs once, when the program initializes.
Now that we understand how a JMS application attaches to WebSphere MQ, let's look at a sample JMS program and how to configure WebSphere MQ to run it. To do so, we will:
1. Configure WebSphere MQ
To configure WebSphere MQ for the sample code, we must:
Create a queue manager.
To run the sample code, we need to have a queue manager. There are many different options available when creating queue managers, but the ones we really care about are that it is configured with a dead letter queue, and that it is configured as the default queue manager:
The dead letter queue is used by the queue manager and Java classes to hold messages that cannot be delivered to their intended destination. It is considered a best practice for each queue manager to have a dead letter queue.
When a queue manager is configured as the default queue manager, applications can access it without knowing its name. This makes our sample code easier to write; as a general rule, an application should not depend on this setting.
There are a couple of ways to define a new queue manager, and probably the quickest for our purposes is from the GUI, WebSphere MQ Explorer:
From the Windows® Start menu, navigate to All Programs => IBM WebSphere MQ => WebSphere MQ Explorer. Once the WebSphere MQ Explorer is running, right-click on the Queue Managers folder. then select New => Queue Manager to start the New Queue Manager wizard. (Figure 2)
Figure 2. Create new queue manager
When the wizard opens, type in the queue manager name
JMSDEMOand check the box to Make this the default queue manager. Next, enter the name of the default Dead Letter Queue which is
SYSTEM.DEAD.LETTER.QUEUE. Be sure to enter it in all capital letters. (Figure 3)
Figure 3. Define queue manager
Pressing the Finish button at his point will build the queue manager with all of the default settings. (Figure 4) Among these are that:
- the queue manager will be started immediately.
- the queue manager will be set to start when the computer is rebooted.
- a new listener will be created and started on port 1414.
The new queue manager should now be visible in the WebSphere MQ Explorer window.
Figure 4. Queue manager list
Create a queue
Defining queues from the WebSphere MQ Explorer is also quite easy (Figure 5):
Click the plus sign next to the JMSDEMO queue manager to expand the folder tree, and then click on the Queues folder. System queues are filtered out by default, and since the queue manager has just been built, there should be no queues visible in the right-hand pane.
Next, right-click on the Queues folder and select New => Local Queue on the context menu to open the Local Queue wizard.
Figure 5. Create a new queue
In the wizard, type
JMSDEMO.QLas the name of the queue and click the Finish button. The JNDI directory entry we create later will look for this specific queue name so enter it exactly as shown. (Figure 6)
Figure 6. Define new queue
When the wizard completes, the new queue should be visible in the Queues window. (Figure 7)
Figure 7. List of queues
Set up publish/subscribe
So far, we have defined and started a queue manager and created a queue for point-to-point messaging. There are a couple of additional steps required to set up for publish/subscribe. The broker stores its internal state in queues we will need to create before we can start it. IBM has provided all the definitions in a command script, so all we need to do is to run the script inside the runmqsc command interpreter. Once that is done, we will set up the publish/subscribe broker to start and end under control of the queue manager.
Open a command window and navigate to the directory where WebSphere MQ is installed. From there, drill down into the Java/bin directory where you will find the MQJMS_PSQ.mqsc script. Execute
runmqscand redirect this script into it as input (as shown in Figure 8). Redirect the output to a file so you can look at it later.
Figure 8. Redirect runmqsc script
Next, we need to configure the broker as a service. WebSphere MQ services are a new feature as of Version 6, and a service named SYSTEM.BROKER is provided for this purpose. All that is required is to place the service under queue manager control and then to start it.
Begin by starting the WebSphere MQ command interpreter
runmqsc. Alter the SYSTEM.BROKER service to be under queue manager control with the command
alter service(SYSTEM.BROKER) control(qmgr). Since the queue manager is already running, it is necessary to start the broker manually the first time. Issue the command
start service(system.broker). (Note that runmqsc parameters are case insensitive unless quoted.) Exit from runmqsc with CTRL-C.
We will be using a topic called JMSDemo, however it is not necessary to define topics in advance when using the default settings. This completes the configurations needed to run the JMSDemo application.
2. Obtain the sample code
The demo application is delivered in a zipped format. Use your favorite unzip utility to unpack the files to your local disk. Select the option to preserve directories so that the files unpack to a new directory on your local disk called
JMSDEMO. Within that directory you will find all of the files required to run the program. Take a moment to familiarize yourself with them:
JMSAdmin.config- Tells the JMSAdmin tool to use a filesystem for the JNDI registry service.
JMSAdmin.bat- executes the WebSphere MQ JMS Administration tool.
JMSDemoPub.bat- executes the sample program as a publisher.
JMSDemoReceive.bat- executes the sample program to consume messages on a queue.
JMSDemoSend.bat- executes the sample program to produce messages on a queue.
JMSDemoSub.bat- executes the sample program as a subscriber.
jmsdemoJNDIbindings.scp- administered object definitions with a connection factory set to use bindings mode.
jmsdemoJNDIclient.scp- administered object definitions with a connection factory set to use client mode.
3. Configure administered objects
Every connection factory or destination used in the sample application must be registered in a JNDI directory with a unique name. The sample application uses the name to look up the JMS administered object. The provider-specific objects are configured with the underlying WebSphere MQ object names and properties. Sample definitions are contained in the .scp files provided with the download file.
It is important to understand the properties of the administered objects because they control the interaction between the JMS application and WebSphere MQ. The settings of the various object properties have a significant impact on the behavior and performance of the JMS application. Yet this configuration is not part of the JMS application; the details of how it is performed are specific to WebSphere MQ.
To configure the needed administered objects:
Configure the connection factory
The connection factory requires that the queue manager name parameter be declared but it does not require that this parameter contain a value. When this parameter is filled in, the value provided must match the queue manager name or the connection will fail. When the value is blank, the connection will succeed using bindings mode if the local queue manager is configured as the default queue manager, or in client mode for any queue manager. In the sample, we left this value blank.
The transport parameter is also required and tells JMS whether to use a client or bindings mode connection. When client mode is used, the host, chan and port parameters must be specified:
host- the hostname or IP address where the queue manager resides.
chan- contains the name of the SVRCONN channel used to connect to the queue manager.
port- the port number that the queue manager is listening on.
Some of the connection factory parameters are not strictly required but are important enough to mention here:
FAILIFQUIESCE- enables the queue manager to interrupt any API call in order to shut down. The default for this parameter is to enable it; be aware that disabling it can have adverse affects on the queue manager, especially when using client mode connections.
SYNCPOINTALLGETS- helps to ensure that no messages are lost by the application. This is especially important when running in client mode because there is latency between the message being removed from the queue and when it is delivered over the network to the application. If the network connection is lost during this period, the message cannot be recovered unless it is under syncpoint. Setting SYNCPOINTALLGETS in the connection factory ensures that the message will be rolled back unless it is acknowledged. The acknowledgement happens automatically so this does not affect the program code. (See the WebSphere MQ Application Programming Guide and the WebSphere MQ Using Java manual for a complete discussion of syncpoint operations.)
For the demo program, two connection factory directory definitions are provided, one configured for bindings mode and another configured for client mode, as shown below.
Bindings mode connection factory definition (from the jmsdemoJNDIbindings.scp file):
#--------------------------------------------------------------- # Connection Factory for Bindings mode # Delete the Connection Factory if it exists DELETE CF(JMSDEMOCF) # Define the Connection Factory DEFINE CF(JMSDEMOCF) + SYNCPOINTALLGETS(YES) + TRAN(bind) + QMGR( ) # Display the resulting definition DISPLAY CF(JMSDEMOCF)
Client mode connection factory definition (from the jmsdemoJNDIclient.scp file):
#--------------------------------------------------------------- # Connection Factory for Client mode # Delete the Connection Factory if it exists DELETE CF(JMSDEMOCF) # Define the Connection Factory DEFINE CF(JMSDEMOCF) + SYNCPOINTALLGETS(YES) + TRAN(client) + HOST(localhost) CHAN(SYSTEM.DEF.SVRCONN) PORT(1414) + QMGR( ) # Display the resulting definition DISPLAY CF(JMSDEMOCF)
The SYSTEM.DEF.SVRCONN channel is present by default on every queue manager. We will use it here for convenience, but it is worth noting that as a best practice SYSTEM.* objects are generally not used. If you wish to run the sample on a queue manager that is administered by someone else, it may be necessary for the WebSphere MQ administrator to define a SVRCONN channel for you to use. In that case, be sure to put the correct channel name in the jmsdemoJNDIclient.scp file.
Configure the destinations
The remaining definitions are common to both the jmsdemoJNDIclient.scp file and the jmsdemoJNDIbindings.scp file.
We already know that every JMS administered object must be registered in a directory accessible via JNDI. In order to map the directory name to the queue or topic name, as it is known to WebSphere MQ, the queue or topic property must be set. There is no default value for this property and it is case sensitive.
The FAILIFQUIESCE property is valid for both queue and topic objects. It does not inherit from the connection factory; however, it does default to the correct value of "YES" so it is not included in the sample definitions. Except for the WebSphere MQversion of the queue name, all other properties can take their default values as well.
Queue definition (in both the jmsdemoJNDIclient.scp and jmsdemoJNDIclient.scp files):
#--------------------------------------------------------------- # Queue Object # Delete the Queue if it exists DELETE Q(JMSDEMOQueue) # Define the Queue object DEFINE Q(JMSDEMOQueue) QUEUE(JMSDEMO.QL) # Display the resulting Queue object definition DISPLAY Q(JMSDEMOQueue)
In addition to the properties pertaining to queues, WebSphere MQ topic definitions include a number of properties that facilitate communications with the publish/subscribe broker. These include different classes of service, subscription durability, and the queues which messages are published to or read from. If you are running the demo on a queue manager which you created, the default values are fine. If you are running on a queue manager administered by someone else, the administrator may provide values for some of these properties, particularly BROKERPUBQ and BROKERSUBQ. The sample definitions take all the default values.
Topic definition (in both the jmsdemoJNDIclient.scp and jmsdemoJNDIclient.scp files):
#--------------------------------------------------------------- # Topic Object # Delete the Topic if it exists DELETE T(JMSDEMOTopic) # Define the Topic DEFINE T(JMSDEMOTopic) TOPIC(JMSDEMOtopic) # Display the resulting Topic definition DISPLAY T(JMSDEMOTopic)
Bind the administered objects
The administered objects created in the previous step need to be registered in the directory before they are available to the JMS application. The registry entry is said to "bind" a JNDI name to a provider-specific resource. WebSphere MQ provides an administration tool that creates and manages administered objects in any JNDI accessible directory service. The sample code includes a script to invoke the WebSphere MQ JMS administration tool, as well as the definition scripts for the administered objects we will be using.
- Open a command prompt and change to the
- Run the JMSAdmin script with the bindings definitions as shown in Figure 9.
Figure 9. Run JMSAdmin
At this point, you should continue to the next step and execute the code. After having successfully executed the sample using bindings mode, you can come back to this step and run the JMSAdmin script using the client mode definitions. This will cause the sample code to connect to the queue manager over TCP/IP, rather than through IPC. You can switch freely between bindings mode and client mode without affecting the sample application. When using client mode, the SVRCONN channel will be visible in the WebSphere MQ Explorer with a status of ACTIVE.
- Open a command prompt and change to the
4. Run the sample code
Now that we've configured WebSphere MQ and defined the administered objects in the JNDI directory, we're ready to run the sample included with this article. To do so, follow these steps:
Execute the point-to-point example
- Open three command prompt windows and change to the
JMSDEMOdirectory in each window.
- To execute the point-to-point sample, run
JMSDemoSend.batin one window (Figure 10) and
JMSDEMOReceive.batin another (Figure 11). The programs will display some diagnostic information and then wait for input.
- Type any message into the JMSDemoSend.bat window and it should appear in the JMSDemoReceive.bat window. Enter a blank line to end.
Figure 10. JMSDemoSend.bat window
Figure 11. JMSDemoReceive.bat window
Notice that in the first window (Figure 10), we sent a message with the contents "Test message." Notice, then, that in the second window (Figure 11), we received a message with the contents "Test message."
- Open three command prompt windows and change to the
Execute the publish/subscribe example
To run the publish/subscribe sample:
- Be sure the publish/subscribe broker is running by entering the
JMSDemoPub.batin one window (Figure 12) and
JMSDemoSub.batin the other two (Figure 13).
- Type any message into the JMSDemoPub.bat window and it will appear in both of the JMSDemoSub.bat windows. Enter a blank line to end.
Figure 12. JMSDemoPub.bat window
Figure 13. The two JMSDemoSub.bat windows should be identical
Notice that in the first window (Figure 12), we sent a message with the contents "Test publication," and in the second and third windows (Figure 13), both received a message with the contents "Test publication."
- Be sure the publish/subscribe broker is running by entering the
In this article, you have seen how a J2SE application can access WebSphere MQ as a messaging provider using JMS and JNDI, without it needing to be deployed in a J2EE application server (such as WebSphere Application Server).
You have seen:
- How a JMS application contains three distinct layers:
- The provider-independent JMS application.
- The provider-specific JMS implementation.
- The JMS provider.
- How an application can attach to WebSphere MQ using either of two modes, bindings and client.
- How the application accesses the JMS administered objects in the JMS implementation layer using JNDI.
- How to configure WebSphere MQ.
- How to administer WebSphere MQ resources so that they can be accessed as JMS administered objects using JNDI.
You are now prepared to deploy your new and existing Java applications to use WebSphere MQ.
The authors would like to thank Graham Oakes and Emir Garza for their help in developing this article.
- WebSphere MQ - The main product page
- WebSphere MQ V6.0 library - All product manuals
- WebSphere MQ Product support - The home for support for WebSphere MQ
- Extended Transactional Client - The client mode WebSphere MQ client that supports XA transactions
- IBM WebSphere MQ Information Center - Core documentation for WebSphere MQ
- WebSphere MQ Using Java - Using WebSphere MQ from Java
- WebSphere MQ System Administration Guide - How to administer WebSphere MQ
- WebSphere MQ - Free 90 Day trial code - (Windows platform) - Use this install if you don't already have WebSphere MQ available
- MQC6: WebSphere MQ V6.0 Clients - Download the WebSphere MQ client for all supported platforms
- Developing a standalone Java application for WebSphere MQ - by Bobby Woolf, developerWorks, February 23, 2005 - The original article for WebSphere MQ V5.3
- JMS 1.1 simplifies messaging with unified domains - by Bobby Woolf, developerWorks, August 1, 2002 - Explains how Queues and Topics are unified in JMS 1.1
- Eliminate caching in service locator implementations in J2EE 1.3 - by Bobby Woolf, developerWorks, October 13, 2004 – Contains a good explanation of JNDI
These articles on the JMS implementation in WebSphere Application Server also discuss how a JMS application interfaces with a messaging provider.
- Deploying message-driven beans and JMS applications into the Service Integration Bus - by Roland Barcia and Saravana Chandran, developerWorks, April 13, 2005 - Discusses how JMS point-to-point works
- Deploying publish and subscribe applications into the Service Integration Bus - by Roland Barcia and Bobby Woolf, developerWorks, August 17, 2005 - Discusses how JMS publish/subscribe works