Getting Started with Microsoft Message Queue Server

By Susie Adams

The growing trend towards distributed application development has created a need for a reliable way to communicate asynchronously among applications running on a distributed network. The Microsoft Message Queue Server (MSMQ), recently introduced with the release of the NT 4.0 Option Pack, is positioning itself to become the messaging product of choice for the Windows platform.

Previously code named "Falcon", MSMQ provides an easy way for Web and Win32 applications running on different servers to communicate with one another by sending and receiving messages. These messages can contain data in any format that makes sense to both the sender and the receiver applications, since an application processes the messages it receives by reading and interpreting the body of the message.

In this article, we'll give you an overview of MSMQ. Then, we'll use the MSMQ components from Microsoft's component library to build an Active Server application that will create, send, and read messages from an MSMQ message queue.

The big picture

In a very broad sense, you could think of Message queuing as an electronic E-mail interface for applications. In other words instead of people sending and receiving messages, applications are sending and receiving messages. When a message is in transit between applications, the message resides in an MSMQ message queue. The MSMQ message queue protects the message from being lost in transit and provides a place for the receiving application to look for new messages.

MSMQ also allows the sending application to continue processing—regardless of whether or not the receiving application has received a message. If the destination application queue is unavailable or the network is down, MSMQ will hold the message and re-send it repeatedly until the application can successfully deliver the message.

There are several different types of communication scenarios that lend themselves to an MSMQ implementation. We've listed a few of them in Table A.

Table A: Asynchronous communication scenarios

Type and Description

Store and Forward:

Use when sending and receiving applications that will run at different times. Example: A remote sales force automation system.

Defensive:

Use when an environment is usually reliable but the cost of losing messages or interrupting messages is high.

Concurrent:

Use when the sending application can't wait for a response from the receiving application.

Journaled:

Use when the requests for services have to be logged or audited, and possibly re-processed.

Connectionless:

Use when the ultimate receiver of the message isn't known in advance.

MSMQ provides a number of additional features, including dynamic routing and configuration, multiple delivery and acknowledgment options, Microsoft Transaction Server integration, and integration with NT security facilities. It runs on both WinNT and 95 platforms and is interoperable with several other platforms.

To facilitate the development of applications that create and read MSMQ messages, Microsoft has provided an ActiveX component library. This library contains the MSMQ application programming interfaces.

Note: The Microsoft Message Queue MSMQ software is part of the Windows NT4.0 Option Pack available for downloading on the Windows NT 4.0 Microsoft Web site. The examples below assume that you've successfully installed the Option Pack on your machine, and that an MSMQ enterprise and site is locally accessible or available over a network connection.

The MSMQ Explorer

MSMQ Explorer displays a logical view of your MSMQ enterprise network. Using the MSMQ Explorer, you can view and modify the properties of sites, connected networks, computers, and message queues.

To open the Explorer, navigate to the Windows NT 4.0 Option Pack's MSMQ Explorer menu option. The ASP application you're going to create requires a message queue to send and retrieve messages, so the first thing you'll need to do is create a new public message queue called Que1 under your local site.

MSMQ can create both public and private queues. Public queues are replicated in the MQIS (an SQL Server 6.5 data store), throughout the enterprise, and can, therefore, be located by any computer within the enterprise. To create the queue, first select your local computer in the site list and right click. In the following menu, select New, then Queue. A dialog should appear requesting a queue name. Enter the name Que1, and then close the dialog to save the new queue. The queue Que1 should now appear under your local computer in the MSMQ Explorer, as shown in Figure A.

Figure A: The MSMQ Explorer allows you to add a new queue.

Reading messages from a queue

MSMQ messages contain the message data that your applications send among themselves. There are two main types of messages: application-generated messages and MSMQ-generated acknowledgment and report messages. In our example, we're going to create an Active Server page that opens the Que1 message queue you just created and then displays the message properties of each message in an HTML table. Later in this article, the same page will create a new message and send it to the same message queue.

To begin, let's concentrate on how you read the messages from the message queue. First, create a new Active Server application in Visual InterDev and name it MSMQ. To do this, open the Visual InterDev Development Studio and select New from the File menu. In the resulting dialog, select the project tab's Web Project Wizard and name the project MSMQ.

Next, create a new Active Server page named MSMQHome.asp by selecting the file menu's New option. In the following dialog, select the Active Server Page option and name the page MSMQHome.asp. You'll find the code for the MSMQHome.asp displayed in Listing A.

Listing A: MSMQHome.asp

<%@ LANGUAGE="VBSCRIPT" %>
<%Response.Buffer = True%>
<%Response.Flush%>

<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual InterDev 1.0">
<META HTTP-EQUIV="Content-Type" content="text/html; charset=iso-8859-1">
<TITLE>MSMQ Test</TITLE>
</HEAD>
<BODY>

<p align="center"><font color="#0000FF" size="5">MSMQ Test
Application</font></p>

<form method="POST">
    <p>Message: <input type="text" size="40"name="txtMessage">
   <input LANGUAGE="javascript" TYPE=button VALUE="Send" ONCLICK="window.location.href='Message.asp?MessageText='+txtMessage.value;"
     NAME="Send">
   </p>
    <p><strong>Que1 Messages</strong> <input type="submit"
    name="B2" value="Refresh Que"></p>
    <div align="center"><center><table border="1" width="100%">
        <tr>
            <th>Label</th>
            <th>Message Text</th>
        </tr>
        <%
      set query = Server.CreateObject("MSMQ.MSMQQuery")

      Set iqs = query.LookupQueue(,,"Que1")
      iqs.Reset

      Set iq = iqs.Next
   
      set myq = iq.Open(32,0)
      If myq.IsOpen Then
         set message = myq.Peek(,,100)
         set message = myq.PeekCurrent(,,100)   

         if message is nothing then %>
<tr><td> No Messages to Process </tr> </td>
         <%else
            do while message <> ""            
               if message is nothing then exit do   
               %>
               <tr>
                  <td><%=message.label%></td>
                  <td><%=message.body%></td>
               </tr>
               <%         
               set message = myq.PeekNext(,,100)      
               if message is nothing then exit do      
            loop
         end if   
      end if
      myq.Close
      %>
    </table>
    </center></div>
</form>

</BODY>
</HTML>

The script you see in Listing A does a lot more than just read and display messages. First, it creates a text box for the message body. Then, it creates a Submit button to submit the page to a second page which we've not yet created (Message.asp). The script also creates a table that contains a list of the messages read from the current Que1 and a Refresh button that re-submits the current page back to itself to refresh the message list HTML table.

For now, enter the entire listing into the Active Server page you just created. In the next few paragraphs, we're going to concentrate only on the pieces of the code that read and display the messages in the HTML table. Figure B shows the completed page as you'd see it in Internet Explorer.

Figure B: The MSMQHome.asp page looks like this in Internet Explorer.

 

Breaking down the code

Our ASP code starts by creating the HTML form field and Submit button. It then creates an HTML table and populates it with messages read from Que1. Before you can read the messages from an existing queue, you need to first locate the queue in the enterprise. To accomplish this task, you use the MSMQQuery ActiveX object, which allows you to query MQIS for existing public queues:

Set iqs = query.LookupQueue(,,"Que1")

The results of the query are now returned to MSMQQuery in an MSMQQueueInfos object—a collection of queues returned as a result of the query and in the MSMQHome example represented by the "iqs" variable. Since the information in the collection is dynamic, there's no queue count available. To traverse through the collection, you must first move the cursor to the start of the collection using the Reset method. Then, use the Next method to move to the first queue in the collection:

iqs.Reset
Set iq = iqs.Next

In this example there's only one queue in the collection, so the iq variable should now represent a handle to the "Que1" queue you created earlier. Next, you need to open the queue with the following syntax:

set object2 = object1.Open (Access, ShareMode)

In the example, you open the queue in MQ_RECEIVE_ACCESS and MQ_DENY_NONE share mode, like so:

set myq = iq.Open(32,0)

Once the queue successfully opens, you can begin to read the messages there. You retrieve the first message in the queue by calling the Peek method of the MSMQQueue object. The Peek method always returns the first message in the queue, or, if the queue is empty, waits for a message to arrive. However, Peek doesn't remove the message from the queue. The Peek method's primary purpose in this example is to put the cursor at the top of the message queue. Look at the following syntax for the Peek method:

set object2 = object1.Peek ([ReceiveTimeout]
    [WantDestinationQueue][, WantBody])

The ReceiveTimeout parameter specifies the amount of time in milliseconds that MSMQ will wait for a message to arrive. If you don't specify a time, MSMQ will wait until a message is received in the queue. The WantDestinationQueue (True, False) tells MSMQ whether you want the destination queue information returned; WantBody (True, False) specifies whether you want the body of the message returned.

After you call the Peek method you must call the PeekCurrent method to initialize the implied cursor. PeekCurrent returns the message at the current cursor position. The syntax for PeekCurrent is as follows:

set object2 = object1.PeekCurrent ([ReceiveTimeout][, WantDestinationQueue][, WantBody])

Now, you can read the message properties for the first message in the queue and display them in the HTML table row, like so:

   ...
   <tr>
      <td><%=message.label%></td>
      <td><%=message.body%></td>
   </tr>
         ...

Next, using the PeekNext method, the script loops through the message queue until the method returns an invalid message object. When the script finishes reading the message queue, you close the message queue using the Close method, as follows:

myq.Close

Note: You must call the PeekCurrent method prior to the PeekNext method to initialize the implied cursor. If the PeekCurrent method isn't called, then MSMQ returns the MQ_ERROR_ILLEGAL CURSOR_ACTION error.

After you've created the page and entered the code in Listing A, save the Active Server Page and test the page in Internet Explorer. You should see a table appear containing one row with the label value of "No Messages to Process," as shown in Figure B.

Sending an MSMQ message

Now that we've successfully read the messages from the queue, let's create a few new messages to populate the HTML message table. In the next few paragraphs, we're going to create an application message and send that message to the new public queue, Que1, in the MSMQ enterprise. The MSMQHome.asp code you created earlier contains an HTML text box and Submit button. If you've already created the script, just follow along as we walk through the code.

The MSMQHome page we created is now going to help us create and send messages as well as read them. The finished page should allow the user to first enter a message in the message text field and then to click on the Submit button. Next, the page should call a new page called message.asp, shown in Listing B, that will create and the new message to the Que1 queue.

Listing B: Calling the message.asp page.

<p>Message: <input type="text" size="40" name="txtMessage">
<input LANGUAGE="javascript" TYPE=button VALUE="Send" ONCLICK="window.location.href='Message.asp?MessageText='+txtMessage.value;"
     NAME="Send">

To create the message.asp page, select the Visual InterDev file menu's New option. In the resulting dialog, select the Active Server Page option and name the page message.asp. Next, add the script in Listing C to the page.

bListing C: The message.asp script.

<%@ LANGUAGE="VBSCRIPT" %>

<%
MessageText =Request.QueryString("MessageText")
set query = Server.CreateObject("MSMQ.MSMQQuery")

Set iqs = query.LookupQueue(,,"Que1")
iqs.Reset

Set iq = iqs.Next

set myq = iq.Open( 2,0)
If myq.IsOpen Then
   Set msgOut = Server.CreateObject("MSMQ.MSMQMessage")
   msgOut.Priority = 4
   msgOut.Body = MessageText
   msgOut.Label = "Test Message"
   msgOut.Send myq
End If
myq.Close

%>

<%Response.Redirect "MSMQHome.asp"%>

In this example, the script once again locates the MSMQ queue named Que1 and opens it. Once the queue opens, the script creates a MSMQMessage object. The MSMQMessage object provides the properties that define a MSMQ message and also provides a single Send method to facilitate the sending of messages to specified queues. The body of an MSMQ message can be a string, an array of bytes, any numeric, date, and currency type that a variant can contain, or any persistent ActiveX object that supports IDispatch and IPersist (IPersistStream or IPersistStorage).

In this example, the message body is set to the contents of the text box and each message is given the same label "Test Message." Once you've created the page and added the code in Listing C, save it and re-browse the MSMQHome.asp page. In the MSMQHome page, enter the message text you wish to send and click the Send button. The message will be created and sent to Que1. Next, check the contents of the queue by pressing the Refresh button. The new message should appear in the HTML table, as shown in Figure C.

Figure C: When you send a new message to the queue, simply click the Refresh Que button to view it.

You can verify that the message is in the queue by using MSMQ to open the MSMQ Explorer and drill down to the Que1 queue. If you don't see the message, you may need to refresh the queue using the Refresh menu option. If you see the message label, click on it; a Properties dialog should appear, displaying the message properties and message body for the message you just created, as shown in Figure D.

Figure D: You can easily see the message and its properties.

MSMQ and MTS

MSMQ is tightly integrated with Microsoft Transaction Server (MTS). All calls to MSMQ from a transaction-enabled ActiveX component, running under MTS, automatically join whatever transaction is active.

Forinstance, let's examine what would happen if you develop an ActiveX component that reads messages from a message queue and then processes them using the message data to update an SQL database. Let's also say the component is MTS-enabled and installed in the MTS environment. Next, let's imagine the component is halfway through processing when an SQL database query fails, your code aborts the transaction, and the database updates roll back. So, what about the messages you read? If MSMQ doesn't roll back the messages, they might be lost. Fortunately, because MSMQ is transaction-aware, it will also roll back and cancel the reads of the queue messages.

Without this interaction, the MSMQ messages would have been lost.

To send a transactional message, you must send it to a message queue that's been identified as a transactional queue. You can, however, read a transactional message without specifying a transactional queue. You declare the transaction status of a queue when you create the queue in the Queue Properties dialog.

Conclusion

Microsoft Message Queue Server is Microsoft's first product offering in the message queue arena. It provides an easy-to-use mechanism for effective communication among applications running on distributed servers. The product also provides a fairly robust set of ActiveX components that facilitate the development of Web and Win32 applications in need of reliable and efficient application messaging facilities.

Susie Adams is a senior consultant with Spectrum Technologies and has more than 11 years application development experience.

Copyright © 1998, ZD Inc. All rights reserved. ZD Journals and the ZD Journals logo are trademarks of ZD Inc. Reproduction in whole or in part in any form or medium without express written permission of ZD Inc. is prohibited. All other product names and logos are trademarks or registered trademarks of their respective owners.