IBM WebSphere MQ is not really built out of the box to provide JMS and Publish/Subscribe. Essentially the JMS implementation is achieved through a broker and a lot of system queues. There are two steps to getting Tomcat to work with MQ.
1.1 MQ Configuration
Prior to configuring the MQ Server 6.0, download the following support packs:
- 6.0.2-WS-MQ-WinIA32-FP0004-EnUs.zip – This is the 6.0.2.4 Update and provides a bit better JMS implementation. It certainly updates the jar files for JMS.
- ms0q.zip – This just makes it easier to see and edit the publish/subscribe topics in the MQ Explorer. It adds a Topic folder to the queue manager.
If you are using MQ 7.0, I believe it has the above and has a totally different JMS implementation and so will require confirmation of the MQ configuration.
The process below assumes some basic knowledge of WebSphere MQ, for example how to create queues. It is also important to understand the connection mode; there are two ways for an application to connect to the WebSphere MQ queue manager, the modes are:
- 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.
1.1.1 Configure WebSphere MQ
1.1.1.1 Create 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.
- 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.
- When the wizard opens, type in the queue manager name QM and 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.
- Select Next and Next. Ensure the Create Server Connection Channel is checked and select Next.
- Enter the port for the Server Connection Channel (1480).
- Pressing the Finish button at his point will build the queue manager with all of the default settings. 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 1480.
- The new queue manager should now be visible in the WebSphere MQ Explorer window.
1.1.1.2 Create a queue.
Defining queues from the WebSphere MQ Explorer is also quite easy:
- Click the plus sign next to the 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.
- In the wizard, type IncomingQueue as 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.
- When the wizard completes, the new queue should be visible in the Queues window.
- Repeat the above process for the OutgoingQueue
1.1.1.3 Create a Channel
- From the Windows® Start menu, navigate to All Programs => IBM WebSphere MQ => WebSphere MQ Explorer.
- Click the plus sign next to the queue manager to expand the folder tree, click the plus sign next to the Advanced to expand the folder tree.
- Next, right-click on the Chanell folder and select New => Server Channel on the context menu to open the Channel wizard.
- Enter the name of the service, SVR_CHANNEL, Select Next and then select Finish.
1.1.1.4 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 runmqsc and redirect this script into it as input. Redirect the output to a file so you can look at it later (see Figure 11).
· Figure 11 - RunMQSC Command
- 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. You can use the method displayed in Figure 11 but it’s a lot easier to go into the WebSphere MQ Explorer and set it up.
- .Click the plus sign next to the queue manager to expand the folder tree, click the plus sign next to the Advanced to expand the folder tree and then click on the Services folder.
- Next, right-click on the Services folder and select New => Service on the context menu to open the Service wizard.
- Enter the name of the service, PublishSubscribeBroker and click the select button to change the service to use as an attribute template, this will open a list of service types.
- Select SYSTEM.BROKER and OK to close the window. Select Next.
- In the next screen, change the service control from Manual to Queue Manager Start.
- Select Finish. The Service is now created. Right mouse click the service and select start.
1.1.1.5 MQ Authorisation
Now the user needs to be authorized for the queue and the queue manager. As the security could be provided by a number of directory services, I have just supplied the command to run. It is assumed that your infrastructure/network group will know how to set the user up in the directory. AIG Australia uses the Active Directory domain.
The commands to run are:
setmqaut -t qmgr -p "test" +all
setmqaut -t qmgr –m QM -p "test" +all
setmqaut -m QM -n IncomingMessage -t queue -p "test" +all
setmqaut -m QM -n OutgoingMessage -t queue -p "test" +all
1.1.2 Tomcat Configuration
First of all, there are a lot of processes on the web for setting up MQ as a JNDI resource for Tomcat. Unfortunately all of them are wrong in some way. This is mostly due to the fact that they are either using bindings mode or are written for an older version of MQ. The IBM web site especially has a lot of articles using the WMQInitialContextFactory or the RefFSContextFactory which use bindings mode, will only work on the MQ server or are plain incorrect.
1.1.2.1 Client Install and Libraries
The Tomcat server requires the MQ client installed and the following libraries installed in the Tomcat\common\lib directory.
Libraries from MQ Client (although this should not be required if the classpath is pointed to the MQ client Java directory correctly):
- com.ibm.mq.jar
- com.ibm.mq.soap.jar
- com.ibm.mqetclient.jar
- com.ibm.mqjms.jar
- connector.jar
- dhbcore.jar
- fscontext.jar
- jms.jar
- jndi.jar
- postcard.jar
Libraries from the Geronimo project (this provides the underlying JMS provider). To be honest I am not sure if this is required but it doesn’t hurt.
- geronimo-j2ee-management_1.1_spec-1.0.1.jar
- geronimo-jms_1.1_spec-1.1.1.jar
1.1.2.2 JMS Code
The JNDI configuration below works for the following JMS code (this code also works for ActiveMQ):
// Lookup JNDI for our connection factory and topics
InitialContext initCtx = new InitialContext();
_connectionFactory = (TopicConnectionFactory) initCtx.lookup(“java:/comp/env/ConnectionFactory”);
_incomingMessageTopic = (Topic) initCtx.lookup(“java:/comp/env/IncomingMessages”);
// Establish connection (if one exists, close it first)
_connection = _connectionFactory.createTopicConnection(_username, _password);
_connection.setClientID(_clientid);
_connection.start();
The main thing to notice in the above code is that it is using topics. The JNDI configuration is also valid for queues. In either case the connection requires a username and password as well as the clientid.
1.1.2.3 JNDI Resource Configuration
The resource configuration is shown below. In this case topics are used. If queues are used the Queue classes have to be used, in which case change the word Topic to Queue (for example, MQQueueConnectionFactory).
The Reference table below provides the extra attributes which can be used. You must use the short form as some of the long forms don’t work.
<Resource name="ConnectionFactory" auth="Container" type="com.ibm.mq.jms.MQTopicConnectionFactory" factory="com.ibm.mq.jms.MQTopicConnectionFactoryFactory" description="JMS Queue Connection Factory for sending messages" HOST="localhost" PORT="1480" CHAN="SVR_CHANNEL" TRAN="1" QMGR="QM"/>
<Resource name="IncomingMessages" auth="Container" type="com.ibm.mq.jms.MQTopic" factory="com.ibm.mq.jms.MQTopicFactory" description="JMS Topic for recieved messages" TOP="IncomingMessages" BPUB="IncomingMessage" />
6.1.2.4 Reference for the resource attributes:
The following table details the attributes which can be used to setup a JNDI resource for WebSphere MQ.
| Property | Short form | Valid values (defaults in bold) |
| BROKERCCDSUBQ | CCDSUB | SYSTEM.JMS.D.CC.SUBSCRIPTION.QUEUE Any string |
| BROKERCCSUBQ | CCSUB | SYSTEM.JMS.ND.CC.SUBSCRIPTION.QUEUE Any string |
| BROKERCONQ | BCON | Any string |
| BROKERDURSUBQ | BDSUB | SYSTEM.JMS.D.SUBSCRIPTION.QUEUE Any string |
| BROKERPUBQ | BPUB | SYSTEM.BROKER.DEFAULT.STREAM Any string |
| BROKERQMGR | BQM | Any string |
| BROKERSUBQ | BSUB | SYSTEM.JMS.ND.SUBSCRIPTION.QUEUE Any string |
| BROKERVER | BVER | V1 - To use the WebSphere MQ broker. Also for use of the WebSphere MQ Integrator V2 or WebSphere MQ Event Broker brokers in compatibility mode. V2 - To use WebSphere MQ Integrator V2 or WebSphere MQ Event Broker brokers in native mode |
| CCSID | CCS | Any positive integer |
| CHANNEL | CHAN | Any string |
| CLEANUP | CL | SAFE ASPROP NONE STRONG |
| CLEANUPINT | CLINT | 60000 Any positive integer |
| CLIENTID | CID | Any string |
| DESCRIPTION | DESC | Any string |
| EXPIRY | EXP | APP - Expiry may be defined by the JMS application. UNLIM - No expiry occurs. Any positive integer representing expiry in milliseconds. |
| HOSTNAME | HOST | Localhost/Any string |
| MSGBATCHSZ | MBS | 10 Any positive integer |
| MSGRETENTION | MRET | Yes - Unwanted messages remain on the input queue No - Unwanted messages are dealt with according to their disposition options |
| PERSISTENCE | PER | APP - Persistence may be defined by the JMS application. QDEF - Persistence takes the value of the queue default. PERS - Messages are persistent. NON - messages are non-persistent. |
| POLLINGINT | PINT | 5000 Any positive integer |
| PORT | | 1414 (for TRANSPORT set to BIND or CLIENT); 1506 (for TRANSPORT set to DIRECT) Any positive integer |
| PRIORITY | PRI | APP - Priority may be defined by the JMS application. QDEF - Priority takes the value of the queue default. Any integer in the range 0-9. |
| PUBACKINT | PAI | 25 Any positive integer |
| QMANAGER | QMGR | Any string |
| QUEUE | QU | Any string |
| RECEXIT | RCX | Any string |
| RECEXITINIT | RCXI | Any string |
| SECEXIT | SCX | Any string |
| SECEXITINIT | SCXI | Any string |
| SENDEXIT | SDX | Any string |
| SENDXITINIT | SDXI | Any string |
| STATREFRESHINT | SRI | 60000 Any positive integer |
| SUBSTORE | SS | MIGRATE/QUEUE/BROKER |
| SYNCPOINTALLGETS | SPAG | Yes/No |
| TARGCLIENT | TC | JMS - The target of the message is a JMS application. MQ - The target of the message is a non-JMS, traditional WebSphere MQ application. |
| TEMPMODEL | TM | Any string |
| TOPIC | TOP | Any string |
| TRANSPORT | TRAN | BIND - Connections use WebSphere MQ bindings. CLIENT - For a client connection DIRECT - For direct connection to WebSphere MQ Event Broker broker |
| USECONNPOOLING | UCP | Yes/No |