essage-oriented middleware (MOM) decouples applications by allowing them to communicate using one of two messaging models: point-to-point messaging and publish/subscribe messaging. The models differ in fundamental ways, but neither requires applications to know the other’s implementation details. Point-to-point messaging achieves only partial decoupling of applications, because you still need to know where to put messages. Publish/subscribe provides a higher degree of independence and reduces design complexity in many cases, but it requires more coding and configuration. Traditionally, MOM shops have opted for point-to-point messaging to avoid the more complex requirements of publish/subscribe.
Enter IBM WebSphere MQ (WMQ), Version 7. This latest release of WMQ aims to make coding and configuring publish/subscribe easier and more intuitive. A previous DevX article focused on the point-to-point messaging capabilities of WMQ. This article explains WMQ's publish/subscribe messaging.
Publish/Subscribe Messaging OverviewPublish/subscribe is the messaging-oriented equivalent of the object-oriented observer design pattern. In publish/subscribe messaging, a sender application creates a message containing the information it wants to send and assigns it a topic that denotes the subject of the information. This message is called a publication. WMQ receives the publication, recognizes the topic, and then distributes the publication to interested applications. Specifically, WMQ publish/subscribe components include:
- Publisher (information producer): This component generates messages (publications) under a certain subject (topic) and sends the publications to a WMQ queue manager. A publisher knows nothing about the recipient(s) of the information.
- Subscriber (information consumer/receiver): This component registers interest in a certain topic(s) with a WMQ queue manager. It also specifies its subscription queue name; that is, the queue where it wants to receive the messages related to this topic. The subscriber knows nothing about the information publishers(s).
- A publications router: This component passes messages from publishers to topic subscribers. Earlier WMQ versions required a broker component on top of a queue manager to enable publish/subscribe. The broker maintained topics and subscriptions, and it routed publications. In WMQ Version 7, IBM changed this approach significantly. The queue manager is now responsible for topics, subscriptions, and routing publications. Also, MQ Explorer for Version 7 allows you to create topics and subscriptions graphically.
|Figure 1. A Basic Publish/Subscribe Setup: Publish/subscribe includes publishers, subscribers, and a queue manager.|
A publish/subscribe system can have many publishers and many subscribers, and often, two or more queue managers communicating with one another. Also, an application can be both a publisher and a subscriber.
A Publish/Subscribe ScenarioSuppose a company sends notifications to its clients via email and Short Message Service (SMS) based on information received from various information providers (say, news and weather services). If the company adds another provider (say, for entertainment), it will have to configure the new provider to write messages to both SMS and email queues. Figure 2 shows the point-to-point implementation for this use case, and Figure 3 shows the publish/subscribe implementation.
Set Up Your Own Publish/Subscribe Use CaseIn this section, you will create a publish/subscribe setup resembling part of the use case in Figure 3. You will create a publisher for the news topic and two subscriptions for the email and SMS applications using the following procedure:
- Create a queue manager.
- Create a news topic.
- Create subscription queues.
- Create subscriptions.
- Create Java Messaging Services (JMS)-administered objects.
- Write publisher and subscriber classes.
- Run the classes.
Don't worry if you haven't used WMQ before. You will use the Eclipse-based WebSphere MQ Explorer, an easy GUI for administering WMQ, to perform basic definitions.
Start WebSphere MQ Explorer as follows: Start –> All Programs –> IBM WebSphere MQ –> WebSphere MQ Explorer. If this is the first time you are starting MQ Explorer, a welcome screen will appear. Just close the welcome screen.
Create a Queue Manager
- In MQ Explorer's Navigator view, right-click Queue Managers and then select New –> Queue Manager. This starts the "Create Queue Manager" wizard.
- On Step 1, enter TestQM as the queue manager name and then click Next (see Figure 4).
- Click Next on the wizard screens for Steps 2 and 3. At Step 4, make sure "Create listener configured for TCP/IP" is checked and the entered port number is free (see Figure 5), and then click Finish.
Create a News Topic
- Under TestQM, right-click Topics and then select New –> Topic to start the "New Topic" wizard.
- Type News.Topic as the topic name (see Figure 6). This represents the WMQ administrative object used to manage the topic. Click Next.
- On the topic properties page, type News in the "Topic string" field (see Figure 7). This string is used when creating JMS administered objects to refer to the News topic. Click Finish.
Create Subscription QueuesNext, you will set up news publications to be delivered to Subscription queues. Create two queues for the email and SMS applications:
- Under TestQM, right-click Queues then select New –> Local Queue to start the "New Local Queue" wizard.
- In the name field, type Email.Queue and click Finish.
- Repeat the above steps to create another queue called SMS.Queue.
Create SubscriptionsIn order to receive a topic's publications, subscribers have to register interest in the topic. They use subscriptions to accomplish this. You can can create subscriptions programmatically or through MQ Explorer. Through the following steps, you will create two subscriptions using MQ Explorer:
- Under TestQM, right-click Subscriptions and then select New –> Subscription to start the "New Subscription" wizard. In the name field, type EmailSubscription and click Next (see Figure 8).
- In the "Change properties" page, press the Select button next to the "Topic name" and then select News.Topic from the displayed topics list. Press OK. On the same page, type Email.Queue in the destination name field (see Figure 9). Click Finish.
- Repeat the above steps to create another subscription called SMSSubscription with the topic set to News.Topic and the destination name set to SMS.Queue.
A Quick Test for Your Publish/Subscribe SetupPerform the following to verify you have correctly completed the setup for the News topic:
- Under TestQM, click Topics.
- In the right pane, right click News.Topic and select "Test Publication" to open the test window.
- In the message data field, type "publish/subscribe test" (or any other text), click the "Publish message" button, and then click the Close button. This should distribute the message to the subscriber queues Email.Queue and SMS.Queue.
- Under TestQM, click Queues.
- In the right pane, right click Email.Queue and select "Browse Messages." When the browse messages window opens, search the "Message Data" column for the text you entered. You should also see the same message in SMS.Queue.
- Right click Email.Queue and select "Clear Messages." Click the Clear button in the "Clear queue" window. Do the same for SMS.Queue.
Create JMS-Administered ObjectsJMS applications require you to wrap vendor-specific objects in JMS-administered objects. To store JMS-administered objects, create a file-based Java Naming and Directory Interface (JNDI) namespace. Start by adding a new initial context:
- Right-click JMS-Administered Objects and then select Add Initial Context.
- On Screen 1:
- Select "File System" for "Where is the JNDI located."
- For the Bindings directory, browse to C:\JNDI-Directory (This directory has to exist).
- Keep note of the factory class and provider URL; you will use them in the Java code (see Figure 10).
- Click Finish.
Figure 10. Add Initial Context Wizard: You will use the factory class and provider URL in the sample class.
Create a Connection Factory
- Right-click Connection Factories and then select New –> Connection Factory. On the first screen, type TestQMConnectionFactory in the name field and click Next (see Figure 11). You will use TestQMConnectionFactory in the JNDI lookup.
- Click Next on Step 2, Step 3, and Step 4.
- On the last page, select the connection tab (on the left) and then click the Select button to select TestQM as "Base queue manager" (See Figure 12). Click Finish.
Create DestinationsJMS destinations wrap WMQ topics and queues. Create a destination corresponding to the News topic:
- Right-click destinations and select New –> Destination to start the "New Destination" wizard.
- In the first step, enter NewsTopic in the Name field and change the Type field to Topic (See Figure 13). Click Next.
- Click Next on the second screen.
- On the last page (Change properties), type News in the Topic field and then click Finish (See Figure 14). This is the topic string you defined when you created the News topic.
- Right-click destinations and then select New –> Destination to start the new "Destination wizard."
- In the first step, type EmailQueue in the Name field and then click Next.
- Click Next on the second screen.
- On the last page, click the Select button next to the "Queue Manager" field and select TestQM from the list.
- Click the Select button next to the Queue field and select Email (See Figure 15). Queue from the list. Click Finish.
- Repeat the above steps to create another Destination called SMSQueue for SMS.Queue. Your destinations should look like the ones in Figure 16.
Coding JMS Publishers and SubscribersAfter you have defined your topics and subscriptions through the MQ Explorer, writing publisher and subscriber applications is easy. To publish a message, you must write a message to a topic (just as you would with a queue). Subscribers simply read messages from queues. The downloadable source code for this article uses generic JMS interfaces, which treat queues and topics uniformly as destinations. It provides compiled classes that include a News publisher and two subscribers (corresponding to the Email and SMS applications).
The following are brief explanations of the classes.
JNDIUtil ClassThis class includes methods to retrieve objects by name through JNDI lookup (see Listing 1). You will use methods in this class to retrieve references to the JMS objects you have already defined.
NewsPublisher ClassThis class publishes messages to the News topic (see Listing 2). The starting point is a connection factory lookup. You use the factory to create a connection:
You use the connection object to create a session:
factory= jndiUtil.getConnectionFactory("TestQMConnectionFactory"); connection = factory.createConnection();
To publish messages, retrieve a News destination object, create a MessageProducer, and then send messages:
session = connection.createSession( transacted, Session.AUTO_ACKNOWLEDGE);
destination = jndiUtil.getDestination("NewsTopic"); producer = session.createProducer(destination); TextMessage message = session.createTextMessage("No News is Good News!"); producer.send(message);
EmailSubscriber and SMSSubscriberThese two classes represent the email application and the SMS application (see Listing 3 and Listing 4). Because you already defined subscriptions in MQ Explorer, the two applications simply read messages from the subscriber queues. The code is similar to the NewsPublisher class, except that it uses a MessageConsumer to retrieve messages from queues:
consumer = session.createConsumer(destination); TextMessage iMsg = (TextMessage) consumer.receive(1000);
Compiling and Running the Sample ClassesThe JAR files required to compile and run the sample classes are automatically added to the CLASSPATH environment variable when you install WMQ. The required JARs are located in C:\Program Files\IBM\WebSphere MQ\Java\lib, including the JARs you need for JMS and JNDI. You just need to add the sample classes from the code download to your CLASSPATH environment variable. To publish messages, run the NewsPublisher:
Run both subscribers after your run the NewsPublisher to retrieve messages. Each class should retrieve its own copy of the messages published by NewsPublisher:
You're done. Your sample classes should compile and run successfully.
java devx.articles.pubsub.EmailSubscriber java devx.articles.pubsub.SMSSubscriber
So the next time you're designing messaging-based applications, don't be so quick to dismiss publish/subscribe. Remember this article and how quickly you were able to get started with publish/subscribe messaging.