Click here to Skip to main content
11,415,711 members (87,501 online)
Click here to Skip to main content

Round Trip Messaging with SAFMQ

, 24 Jan 2006
Rate this:
Please Sign up or sign in to vote.
Describes the process for implementing a round trip, query-response message interaction with SAFMQ.

Introduction

Query-response applications are very important in computer technology. We use them every day. In fact, you are using one now as you read this article. Your web browser sent a query to the servers at www.codeproject.com, it received the response in the form of text encoded as HTML, which your browser displays to you right now. Query-response applications aren’t just for the web, but for accessing a database server, or receiving files from a file server; even creating users in Windows 2000 and Windows XP uses a query response architecture.

SAFMQ is really a type of middleware, or software that works between two applications so they can communicate with each other. Although SAFMQ has Store and Forward Message Queuing, it also is tuned for query-response applications. Each message enqueued in the SAFMQ server is given a unique UUID (also known as GUID). This value is based off the MAC address of the server and the date and time it was created, (down to the millisecond) using RFC 4122 on UNIX systems, and Microsoft’s implementation on Windows based systems. This UUID is available to both the sender of the message and the receiver. In addition to the automatically generated UUID, a message also has a “Receipt ID,” which can be specified by the sender. Receivers can call a special version of Retrieve which specifies a Receipt ID, and causes the caller to wait until a message is retrievable with a matching Receipt ID.

Here’s a collaboration diagram that may help describe the Round-Trip Query-Response architecture:

Now, there are some special features that you can use with Round-Trip messaging. One is the ability to specify the amount of time a message may live on a queue. This value known as “Time To Live” tells the SAFMQ server to automatically remove the message from the queue if it has been on the queue too long. Also, a client can request that it be notified when a message expires, and the SAFMQ server will generate a response message in this case.

Background

If you aren’t familiar with SAFMQ, you can find out more about it here.

Using the code

Here’s a sample server and client:

// safmq_rt_client.cpp
// Sample round trip client.
 
#include <iostream>
#include "safmq.h"
#include "lib/MessageQueue.h"
#include "lib/MQFactory.h"
 
using namespace std;
using namespace safmq;
 
int main(int argc, char* argv[])
{
 QueueMessage     query, response;

 try {
     MessageQueue* query_que = 
       MQFactory::BuildQueueConnection("safmq:" 
       "//user:password@localhost/query","","");
     MessageQueue* response_que = 
       MQFactory::BuildQueueConnection("safmq:" 
       "//user:password@localhost/response","","");


     // build our request message, specify
     // the query must be received in 5 seconds
     query.setTimeToLiveSeconds(5);
     //Note: without the next line,
     // we won't be notified of timeouts
     query.setTTLErrorWanted(true);

     // Tell the responder where to send the responses
     query.setResponseQueueName("safmq" 
                "://localhost/resposne");

     // Build the body of the query.
     query.setBodyType(BT_TEXT);
     *query.getBufferStream() << "Hello";
     query.setLabel("query");

     // send the request
     ErrorCode        ec = query_que->Enqueue(query);
     if (ec == EC_NOERROR) {
        uuid id = query.getMessageID();
 
       // Look for a response, retreive
       // the body, for message with "id", 
       // wait an infinite amount of time
       // and place the result in "resposne"
       ec = response_que->RetrieveID(true, 
                             id,-1,response);
       if (ec == EC_NOERROR) {
               
         if (response.getMessageClass() == 
                       MC_SYSTEMERRMSG) {
           // We received a system error
           // message, probably a timeout
           cerr << response.getLabel() << endl;
         } else {
         // Output the result.
         cout << response.getBufferStream()->rdbuf() 
              << endl;
       }
     } else {
       cerr << "Retreiving the result gave ErrorCode:" 
            << ec << endl;
     }
   } else {
     cerr << "Sending the query gave ErrorCode:" 
          << ec << endl;
   }

   // Release the instance of the queue
   delete query_que;
   delete response_que;
 } catch (ErrorCode e) {
   cerr << "ErrorCode: " << e 
        << " received." << endl;
 } catch (exception& e) {
   cerr << e.what() << endl;
 }
 return 0;
}
 

////////////////////////////////////////////////
////////////////////////////////////////////////
 
// rt_server.cpp
// Sample Round Trip Server
 
#include <iostream>
#include <string>
#include "safmq.h"
#include "lib/MessageQueue.h"
#include "lib/MQFactory.h"
 
using namespace std;
using namespace safmq;
 
int main(int argc, char* argv[])
{
 QueueMessage     query, response;

 try {
     MessageQueue* query_que = 
        MQFactory::BuildQueueConnection("safmq:" 
        "//user:password@localhost/query","","");
     MessageQueue* response_que = NULL;
     SAFMQ_WSTRING response_name;

     // Retreive the query
     ErrorCode ec = query_que->Retrieve(true,-1,query);

     if (ec == EC_NOERROR) {
          // Create a response message
          response.setLabel("response");
          // tie the response to the
          // request with the ReciptID

          response.setReciptID(query.getMessageID());
          response.setBodyType(BT_TEXT);
          *response.getBufferStream() << "Hi!" 
                                      << endl;

          // Get and open the queue
          // that is the response queue
          response.getResponseQueueName(response_name);

          response_que = 
            MQFactory::BuildQueueConnection(response_name, 
            "user","password");
          
          // Send the response
          response_que->Enqueue(response);

          delete response_que;
     }

     // Release the instance of the queue
     delete query_que;
 } catch (ErrorCode e) {
         cerr << "ErrorCode: " << e 
              << " received." << endl;
 } catch (exception& e) {
         cerr << e.what() << endl;
 }
 return 0;
}

History

Updates and documentation for SAFMQ can be found at SourceForge.net.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

mattbattey
Architect
United States United States
A programmer for 20 years and professionaly employed for 12, I am currently Cheif Engineer for Pharmacy Chare Professionals, Inc., located in Omaha, NE.

My experience is in the area of OO Design, Application, and programming, technical team leadership, RDBMS applications, ISAM applications, Image Processing, Mathematical image generation, Client-Server business applications, eBusiness applications, XML & EDI B2B communications, Java application development, C/C++ application development, CFML/ASP/VB development, on systems like Win2K/NT/98/95, Linux, Irix, Solaris, and MacOS.

Comments and Discussions

 
QuestionGetting the response_name in the server program Pin
itowi5-Feb-07 7:25
memberitowi5-Feb-07 7:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150427.4 | Last Updated 24 Jan 2006
Article Copyright 2006 by mattbattey
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid