Using M essage
Queues
I
n this c hapter, I want to talk abo ut Mic ro so ft Message Queues, inc luding what they are, ho w they wo rk, and when they might be useful fo r yo ur applic atio ns.How M essage Queuing Works
Me ssage que uingis a to o l that helps two pro grams c o mmuni-c ate with eammuni-c h o ther in an asynmmuni-c hro no us fashio n. This means that a c lient pro gram c an send a request to a server and then c o ntinue pro c essing witho ut waiting fo r the server pro c ess to c o mplete. When the server pro c ess has finished pro c essing the request, it will return the message to the c lient pro gram, whic h will be no tified with the respo nse it available to be pro -c essed.
Well, kinda, sorta: While not strictly a part of the COM+ program m ing environm ent, Microsoft Message Queuing w orks closely w ith COM and COM+ com ponents to im ple-m ent high-perforple-m ance applications.
Synchronous processing
No rmally, when yo u are using a COM c o mpo nent and yo u issue a metho d, o r request the info rmatio n in a pro perty, yo ur pro gram must wait until the metho d o r pro perty returns c o n-tro l to yo ur pro gram. This is c alled synchro no us pro ce ssing.
In sync hro no us pro c essing, the c lient pro gram begins by send-ing a request to the server to perfo rm a spec ific task. The server pro gram rec eives the request, perfo rms the task, and returns the result bac k to the c lient. During the time the server is pro c essing the c lient’s request, the c lient pro gram is in a wait
state, where it c an’t perfo rm any pro c essing. It will o nly resume pro c essing after the server has returned its respo nse (see Figure 19-1).
Synchronous processing made simple: When thinking about synchronous pro-cessing, visualize how a Web brow ser w orks. The URL is used to generate a request to the Web server and then the brow ser w aits for the Web page to be returned.
Figure 19-1: Processing a synchronous request
Asynchronous processing
In so me c ases, it’s useful fo r yo ur pro gram to issue a request fo r info rmatio n and then perfo rm o ther tasks while yo ur pro gram waits fo r the respo nse. This is c alled
asynchro no us pro ce ssing.
In async hro no us pro c essing, the c lient pro gram begins by sending a request to the server to perfo rm a spec ific task and then resumes its no rmal pro c essing. The server rec eives the request, pro c esses it, and returns the result. When the result is rec eived, the c lient pro gram is no tified that the result is available and ready fo r the c lient pro -gram to use (see Figure 19-2).
Asynchronous processing made simple: One w ay to understand how asyn-chronous processing w orks is to com pare it to electronic m ail. You can send a m essage to som eone requesting a piece of inform ation and then continue reading and sending other e-m ail until you receive a response to your original m essage.
Tip
Request
Response
Client
Server
Figure 19-2: Processing an asynchronous request
Sinc e the c lient is no lo nger tightly c o upled to the server, the server has the free-do m to pro c ess requests in the mo st effic ient manner. Sinc e it is quite po ssible that multiple c lients will be sending requests, all o f the messages are sto red in a queue as they are rec eived. As the server finishes pro c essing o ne request, it will pull the next request fro m the queue. This ensures that all o f the messages are pro c essed in the o rder in whic h they were rec eived.
Benefits of message queuing
Using message queues will inc rease the c o mplexity o f yo ur applic atio n. In additio n, no t all applic atio ns will benefit fro m using message queuing. Ho wever, the benefits o f message queuing may o utweigh the extra c o mplexity.
Component availability
Just bec ause yo u have a full-time c o nnec tio n to the server do esn’t mean that the server will always be available. The server’s o perating system o r the applic atio n running o n the server may have c rashed. Netwo rking pro blems are pro bably mo re c o mmo n, espec ially if the server is lo c ated in ano ther building o r ac ro ss the c o un-try fro m yo ur c lient mac hines.
Client Server
Request Client
Request Queue
Client Response
Queue
Server Request
Queue
Server Request
If yo u are unable to reac h the server fo r any reaso n, all o f the requests are buffered lo c ally until the server c an be reac hed. When the server bec o mes available, the info rmatio n that was buffered lo c ally will be transmitted to the server fo r pro c ess-ing. Also , any results that the server may have pro c essed will be rec eived into lo c al sto rage fo r the c lient to pro c ess.
Component performance
By queuing requests fo r pro c essing, the user need no t wait fo r the server to finish pro c essing o ne request befo re starting o n the next request. Thus, yo u c an c reate yo ur applic atio n to prio ritize ho w the pro c essing is do ne. This is impo rtant when yo ur server bec o mes o verlo aded. Tho se tasks that need an immediate respo nse, suc h as c hec king invento ry levels, c an be handled as a no rmal COM+ o bjec t. Tho se tasks that are no t as time-sensitive, suc h as printing an invo ic e, c an be deferred until the server is less busy by using message queuing.
Component lifetimes
Delays c aused by transmitting info rmatio n o ver the netwo rk and interac ting with the user extend the amo unt o f time that an o bjec t ac tually exists inside the transac -tio n server. By using message queuing, the exc hange o f info rma-tio n is handled o ut-side the transac tio n server. This means that the o bjec t exists fo r far less time than it wo uld witho ut using message queuing. This translates into better perfo rmanc e in the transac tio n server, bec ause fewer system reso urc es are needed to pro c ess the ac tual transac tio n.
Disconnected applications
If yo u c reate queues that go in bo th to the server and to the c lient, yo u may no t need a full-time c o nnec tio n to the server. Requests c an be queued up until a c o n-nec tio n to the server is established. Then the requests are transmitted to the server fo r pro c essing using the server queue. Any respo nses that the server has fo r the c lient c an be queued in the c lient queue. When the c o nnec tio n is established, bo th queues will be transmitted to the o ther mac hine. If the c o nnec tio n remains up fo r eno ugh time, the server may ac tually be able to respo nd to the requests sent by the c lient and return them via the reverse queue.
M essage reliability
Server scheduling
Ano ther advantage o f message queuing is the ability to shift the wo rk sitting in a queue to a time when the server is less busy. Thus, message queues have the ability to duplic ate the batc h-pro c essing features o f the mainframe wo rld by making it easy to shift wo rk to a less busy time.
Load leveling
One pro blem with mo st server-driven applic atio n systems is that their wo rklo ad c an vary greatly o ver time, whic h may have an adverse impac t o n perfo rmanc e. In a sync hro no us enviro nment, a server c an easily get o verwhelmed fo r a few mo ments at a time. If this happens o c c asio nally, the server c an c atc h up and no bo dy will no tic e. On the o ther hand, if this happens frequently, the o perating system and the server applic atio n will be fo rc ed to spend extra reso urc es managing the extra wo rk, whic h means that there are less reso urc es to pro c ess the extra wo rk.
This extra o verhead c an be eliminated by using message queuing ( async hro no us pro c essing) . Yo u wo uld tune the server and the applic atio n to get the highest per-fo rmanc e. Then yo u wo uld stage the requests in a message queue until the server c an pro c ess them. Mo st o f the time, the requests wo uld be pulled fro m the message queue as fast as they arrive. Ho wever, when the requests arrive faster than the server c an pro c ess them, they will remain in the message queue until the server c an pro c ess them.
In real terms, the slight penalty impo sed by using message queuing will no t make a big differenc e in the time it takes to pro c ess a request until the server bec o mes o ver-lo aded. Then, depending o n ho w o verver-lo aded the server is, using message queuing will inc rease the time to pro c ess eac h request. Ho wever, bec ause the applic atio n is c o ntinuing to pro c ess requests at o ptimal speed, the time the request spends in the message queue, plus the time it takes the applic atio n to pro c ess the request, will mo st likely be less than the time it takes to pro c ess the request while the server is o verlo aded.
Too much is just right:A long tim e ago, I ran into a situation w here one of the com puters I w as responsible for w as running at m axim um capacity. The CPU uti-lization w ould stay at 100% for several m inutes at a stretch. Response tim e w as horrible. Upgrading to a CPU that w as tw ice as fast solved the problem . How ever, the CPU utilization w as about 40%, rather than the expected 50%. After a lot of digging and analysis, I determ ined that the old CPU w as w asting nearly 20% of its capacity trying to m anage the extra requests. With the faster CPU, the overload condition never arose and the CPU cycles w ere never w asted. While it is not alw ays possible to double your CPU capacity, you m ay be able to use a tool like m essage queuing to ensure that the your CPU isn’t w asting extra cycles trying to m anage too m uch w ork.
M icrosoft M essage Queuing
In o rder to use message queues in a Windo ws enviro nment, yo u need a piec e o f so ftware c alled Mic ro so ft Message Queuing ( o ften abbreviated MSMQ) . It runs o n Windo ws 9x, Windo ws NT, and Windo ws 2000, tho ugh yo u may need the appro pri-ate patc hes to run it. It is c o nsidered a base c o mpo nent o f these o perating systems; thus, there isn’t a separate c harge fo r the so ftware.
Requests and responses
A request is sent to the server using an o bjec t c o ntaining all o f the info rmatio n needed to pro c ess the request. The o bjec t must be persistable and be less than fo ur megabytes in length.
There are fo ur basic respo nses to a request.
✦No re sponse is ne ce ssary– this means that the message sent by the c lient either do esn’t need a respo nse o r the respo nse will be returned using a differ-ent tec hnique. Fo r instanc e, the message sdiffer-ent by the c lidiffer-ent may request a repo rt that will be returned by e-mail.
✦Trigge r an e ve nt in the clie nt application– this means that the server appli-c atio n will fire an event in the appli-c lient pro gram when the server appliappli-c atio n has finished pro c essing the message.
✦Use a synchronous me thod to che ck on the status– this means that the server applic atio n may expo se a pro perty that a c lient applic atio n c an ac c ess to determine if their message has been pro c essed.
✦Use message queuing to receive a response– this is pro bably the mo st c o m-mo n way to determine the o utc o me o f pro c essing a request. Co nsider the c ase o f a salesperso n that enters o rders into a lapto p c o mputer while at a c usto mer’s site. At the end o f the day, the salesperso n c o uld c o nnec t the lapto p to the c o m-pany’s applic atio n server. Then MSMQ wo uld transfer the lo c al messages to the message queues o n the server, while do wnlo ading any respo nses fro m the server into lo c al sto rage fo r the salesperso n to bro wse at his o r her leisure.
Types of queues
There are six basic types o f queues. The type o f queue dic tates ho w the queue will be used, but underneath, the same basic tec hno lo gy is used to suppo rt all o f these types:
✦Me ssage– this is the mo st c o mmo n type o f queue and is used primarily by applic atio ns. Clients c an send messages to the queue, while server applic a-tio ns c an retrieve messages fro m the queue.
✦Administration– this type o f queue is used by an applic atio n to retrieve sta-tus info rmatio n abo ut messages in a message queue. Fo r example, an
ac kno wledgement message indic ates that a message was rec eived o r retrieved fro m the applic atio n at the queue’s destinatio n.
✦Re sponse– this type o f queue is used by c lient applic atio ns to rec eive respo nses fro m the server applic atio n.
✦Re port– this type o f queue trac ks the pro gress o f the messages as they mo ve thro ugh the system.
✦Journal– this type o f queue ho lds messages that have been retrieved at their destinatio n.
✦De ad-le tte r– applic atio n messages that c an’t be delivered are sto red in this type o f queue.
Public and private queues
Queues c an also be labeled as public o r private. Public que ue sare registered in the Ac tive Direc to ry and c an be lo c ated by anyo ne with ac c ess to the Ac tive Direc to ry. Yo u c an searc h fo r vario us pro perties o f a queue in the Ac tive Direc to ry so that yo u c an lo c ate the c o rrec t o ne. Thus public queues c an o nly be implemented o n a Windo ws 2000 Server based system.
Co mbining the name o f the c o mputer with the name o f the queue c reates the name o f a public queue. So , the queue MyQueueo n the Athenawo uld be kno wn as
Athena\MyQueue.
Actively seeking directory information:The Active Directory facility in Window s 2000 Server is a tool that stores inform ation about the resources on the local com -puter, or resources that can be found elsew here on the netw ork. Window s 2000 m akes extensive use of this facility to store inform ation about the operating system , such as user nam es, like public queues, other specialized services, and so on. Private queuesare registered on an individual com puter and can be found by any-one w ho know s the nam es of the com puter and the queue. You m ust also include the keyw ord \Private$in the nam e of the queue, so a private queue on Athena called MyQueuew ould be w ritten as Athena\Private$\MyQueue.
By default, all queues are public . To make a queue private, yo u must inc lude
\Privatein the name o f the queue when it is c reated. Yo u must have ac c ess to an Ac tive Direc to ry server to do this, ho wever. No te that private queues c an be c reated o n Windo ws 98- and Windo ws NT-based mac hines.
M essage queuing and COM + transactions
COM+ transac tio ns using message queues wo rk auto matic ally with the COM+ trans-ac tio n server and the ObjectContexto bjec t. Getting the ObjectContexto bjec t and perfo rming the SetComplete,o r SetAbort,metho d auto matic ally ro lls bac k any o peratio ns yo u made to the queues. In o ther wo rds, no messages are remo ved fro m the queues o r physic ally sent until the transac tio n is either c o mmitted o r ro lled bac k.
There is o ne big issue abo ut using message queues and transac tio ns. While inside a transac tio n, yo u c an o nly send messages to transac tio nal queues — queues that were c reated with the IsTransactionalparameter o f the MSMQQueueInfo.Create
metho d set to True. Also , any messages that are sent auto matic ally have their
MSMQMessage.Priorityvalue set to zero . This ensures that the messages are pro -c essed in the o rder in whi-c h they were re-c eived.
The message queues also inc lude their o wn versio n o f transac tio n suppo rt in c ase yo u do n’t want to use the COM+ transac tio n server o r want to wo rk o utside its c o ntro l. Yo u need to use the MSMQCoordinatedTransactionDispenserto begin a transac tio n while under c o ntro l o f the COM+ transac tio n server. Use the
MSMQTransactionDispensero bjec t if yo u’re no t under c o ntro l o f the COM+ trans-ac tio n server. Then use the MSMQTransactiono bjec t to either c o mmit the transac -tio n o r abo rt the transac -tio n.
M essage Queuing Object M odel
Like mo st Windo ws to o ls, the MSMQ is ac c essed via a series o f COM c o mpo nents. Figure 19-3 sho ws a brief o verview o f the o bjec ts and ho w they are related to eac h o ther.
✦MSMQQue ry– is used to searc h the Ac tive Direc to ry fo r public queues. It returns an MSMQQueueInfosc o llec tio n c o ntaining the set o f message queues that met the searc h c riteria.
✦MSMQQue ue Infos– c o ntains a set o f MSMQQueueInfoo bjec ts. This c o mpo -nent c o ntains the results o f an MSMQQueryo peratio n.
Figure 19-3: The Message Queuing Object Model
✦MSMQQue ue– is the base o bjec t in the o bjec t mo del. Yo u use this o bjec t to ac c ess the individual messages in the queue.
✦MSMQMe ssage – ho lds a message that is put in a queue o r rec eived fro m a queue.
✦MSMQEve nt– is used to define queuing events in yo ur applic atio n. These events are fired as info rmatio n arrives at yo ur applic atio n.
M aking it simpler: To sim plify this discussion of m essage queues, I’m going to focus on private queues, w hich m eans that I’m going to ignore the MSMQQuery
and MSMQQueueInfosobjects. The only function lost by om itting the discussion of these objects is the ability to dynam ically locate the proper queue by nam e only. To access a private queue, you m ust know the its nam e as w ell as the com -puter w here it exists.
To add message queuing to yo ur applic atio n, yo u need to selec t the Mic ro so ft Message Queue 2.0 Objec t Library in the Referenc es dialo g bo x ( see Figure 19-4) . To display this dialo g bo x, c ho o se Pro jec t ➪Referenc es fro m the main menu.
Note
M SM QQuery M SM QQueueInfosv
M SM QQueueInfo
M SM QQueueInfo
Figure 19-4: Selecting the Microsoft Message Queue Object Library
The M SM QQueueInfo Object
The MSMQQueueInfoo bjec t is used to c reate o r o pen a message queue. It c an also set and return info rmatio n abo ut a partic ular queue.
M SM QQueueInfo object properties
Table 19-1 lists the pro perties o f the MQMQQueueInfoo bjec t.Table 19-1
Properties of the M SM QQueueInfo Object
Property Description
Authenticate A Longvalue that specifies w hether the queue accepts only authenticated m essages.
BasePriority A Longthat specifies a base priority for all m essages sent to a public queue.
CreateTime A Datevalue containing the date and tim e the public queue w as created.
IsTransactional A Booleanvalue w hen Truem eans only m essages from transactions w ill be accepted into the queue.
Property Description
Journal A Longw hen set to MQ_JOURNAL(0) m eans that the m essages aren’t saved; MS_JOURNAL(1) m eans that w hen a m essage is rem oved from the queue, it is stored in the journal queue.
JournalQuota A Longcontaining the size in kilobytes of the journal queue.
Label A Stringvalue containing up to 124 characters that describe the queue.
ModifyTime A Datevalue containing the date and tim e w hen the properties of the queue w ere last m odified.
PathName A Stringcontaining the path nam e of the queue. This value is in the form of \system\queueor
\system\PRIVATE$\queue.
PathNameDNS A Stringcontaining the path nam e of the queue, w here the system nam e is fully qualified.
PrivLevel A Longw hen set to MQ_PRIV_LEVEL_NONE(0) m eans that the queue accepts only unencrypted m essages;
MQ_PRIV_LEVEL_OPTIONAL(1) m eans that the queue doesn’t enforce privacy (default); or MQ_PRIV_LEVEL _BODY(2) accepts only encrypted m essages.
QueueGuid A Stringcontaining the GUID of the queue.
Quote A Longcontaining the m axim um size of the queue in kilobytes.
ServiceTypeGuid A Stringcontaining the type of service provided by the queue.
M SM QQueueInfo object methods
The MSMQQueueInfoo bjec t c o ntains metho ds fo r managing queues.
Sub Create ([IsTransactional], [IsWorldReadable])
IsTransactionalis a Booleanwhen Truemeans o nly messages fro m transac -tio ns will be ac c epted into the queue.
IsWorldReadableis a Booleanwhen Trueindic ates that everyo ne c an read the messages in the queue.
Sub Delete( )
The Deletemetho d deletes the queue asso c iated with this o bjec t.
Function Open(Access As Long, ShareM ode As Long) As M SM QQueue
The Openmetho d returns an o bjec t referenc e to MSMQQueuespec ified by thePathNamepro perty.
Accessis a Longvalue spec ifying the level type o f ac c ess to the queue. Multiple val-ues may be c o mbined by adding them to gether. Valval-ues are MQ_RECEIVE_ACCESS(1) means that messages c an be rec eived o r peeked at in the queue; MQ_SEND_ACCESS
(2) means that messages c an be sent to the queue; and MQ_PEEK_ACCESS(32) means that yo u c an peek at messages in the queue, but no t remo ve them.
ShareModeis a Longspec ifying ho w the queue is shared. A value o f MQ_DENY_NONE
( 0) means that the queue is shared with everyo ne ( yo u must use this value if yo u spec ify MQ_SEND_ACCESSo r MQ_PEEK_ACCESS) ; o r MQ_DENY_RECEIVE_SHARE( 1) prevents anyo ne exc ept tho se in this pro c ess fro m ac c essing the queue ( this value sho uld be used when yo u spec ify MQ_RECEIVE_ACCESS) .
Sub Refresh( )
The Refreshmetho d gets a fresh c o py o f the pro perties asso c iated with this queue.
Sub Update( )
The Updatemetho d updates the Ac tive Direc to ry fo r a public queue o r the lo c al c o mputer with the c urrent pro perty values fo r this queue.
The M SM QQueue Object
M SM QQueue object properties
Table 19-2 lists the pro perties o f the MQMQQueueo bjec t.Table 19-2
Properties of the M SM QQueue Object
Property Description
Access A Longvalue indicating w hether you can send m essages, peek at m essages, or receive m essages from the queue.
Handle A Longcontaining a handle of the open queue.
IsOpen A Booleanvalue w hen Truem eans that the queue is open.
QueueInfo An object reference to a MSMQQueueInfoobject containing additional inform ation about the queue.
ShareMode A Longthat indicates w hether the queue is available to everyone or w hether only this process.
M SM QQueue object methods
The MSMQQueueo bjec t c o ntains metho ds fo r examining the c o ntents o f the queue.
Sub Close( )
The Closemetho d c lo ses the queue.
Sub EnableNotification(Event As M SM QEvent, [Cursor],
[ReceiveTimeout])
The EnableNotificationmetho d instruc ts the message queuing so ftware to trig-ger events using the MSMQEvento bjec t. No te that this o bjec t needed to be dec lared using the WithEventskeywo rd in o rder to rec eive the events. Yo u c an spec ify that the event will be fired when there is a message in the queue, when a message is at the queue’s c urrent lo c atio n, o r when a message is at the queue’s next lo c atio n. No te that it may be po ssible that multiple messages may be in fro nt o f the message that triggered the event.
Eventis an o bjec t referenc e to an MSMQEvento bjec t that has been dec lared
Cursoris an enumerated type that spec ifies the ac tio n o f the c urso r. A value o f
MQMSG_FIRST( 0) means that the event will be fired when a message is in the queue. A value o f MQMSG_CURRENT( 1) means that the event will be fired when a message is at the c urrent lo c atio n o f the c urso r. A value o f MQMSG_NEXT( 2) means that the event will be fired when a message is at the new c urso r lo c atio n.
ReceiveTimeoutis a Longc o ntaining the number o f millisec o nds that MSMQ will wait fo r a message to arrive.
Function Peek([WantDestinationQueue], [WantBody], [ReceiveTimeout])
As M SM QM essage
The Peekmetho d returns the first message in the queue witho ut rec eiving the mes-sage fro m the queue. If the queue is empty, it will wait fo r a mesmes-sage to arrive.
WantDestinationQueueis a Booleanwhen Truemeans that the MSMQMessage. DestinationQueueInfopro perty will be updated to c o ntain the info rmatio n abo ut the destinatio n queue. If no t spec ified, a value o f Falsewill be assumed.
WantBodyis a Booleanwhen Truemeans that the bo dy o f the message sho uld be returned ( default) . Set this value to Falseto reduc e the amo unt o f time to return the message.
ReceiveTimeoutis a Longc o ntaining the number o f millisec o nds that MSMQ will wait fo r a message to arrive.
Function PeekCurrent([WantDestinationQueue], [WantBody],
[ReceiveTimeout], [WantConnectorType]) As M SM QM essage
The PeekCurrentmetho d returns the c urrent message in the q ueue witho ut rec eiving it.WantDestinationQueueis a Booleanwhen Truemeans that the MSMQMessage. DestinationQueueInfopro perty will be updated to c o ntain the info rmatio n abo ut the destinatio n queue. If no t spec ified, a value o f Falsewill be assumed.
WantBodyis a Booleanwhen Truemeans that the bo dy o f the message sho uld be returned ( default) . Set this value to Falseto reduc e the amo unt o f time to return the message.
ReceiveTimeoutis a Longc o ntaining the number o f millisec o nds that MSMQ will wait fo r a message to arrive.
Function PeekNext([WantDestinationQueue], [WantBody],
[ReceiveTimeout], [WantConnectorType]) As M SM QM essage
The PeekNextmetho d returns the next metho d in the queue witho ut rec eiving the message.
WantDestinationQueueis a Booleanvalue when Truemeans that the
MSMQMessage.DestinationQueueInfopro perty will be updated to c o ntain the info rmatio n abo ut the destinatio n queue. If no t spec ified, a value o f Falsewill be assumed.
WantBodyis a Booleanwhen Truemeans that the bo dy o f the message sho uld be returned ( default) . Set this value to Falseto reduc e the amo unt o f time to return the message.
ReceiveTimeoutis a Longvalue c o ntaining the number o f millisec o nds that MSMQ will wait fo r a message to arrive.
WantConnecterTypeis a Booleanwhen Truemeans that c o nnec to r info rmatio n will also be retrieved. If no t spec ified, a value o f Falsewill be assumed.
Function Receive([Transaction], [WantDestinationQueue], [WantBody],
[ReceiveTimeout], [WantConnectorType]) As M SM QM essage
The Receivemetho d returns the first message in the queue and remo ves it fro m the queue.
Transactionis an MSMQTransactiono bjec t o r o ne o f these values: MQ_NO_ TRANSACTION( 0) , whic h means that c all is no t part o f a transac tio n; MQ_MTS_ TRANSACTION( 1) , whic h means that the c all is made as part o f the c urrent MTS o r COM+ transac tio n; MQ_XA_TRANSACTION( 2) , whic h means that the c all is part o f an externally c o o rdinated, XA-c o mpliant transac tio n; o r MQ_SINGLE_MESSAGE
( 3) , whic h means that the c all retrieves a single message.
WantDestinationQueueis a Booleanwhen Truemeans that the MSMQMessage. DestinationQueueInfopro perty will be updated to c o ntain the info rmatio n abo ut the destinatio n queue. If no t spec ified, a value o f Falsewill be assumed.
WantBodyis a Booleanwhen Truemeans that the bo dy o f the message sho uld be returned ( default) . Set this value to Falseto reduc e the amo unt o f time to return the message.
WantConnecterTypeis a Booleanwhen Truemeans that c o nnec to r info rmatio n will also be retrieved. If no t spec ified, a value o f Falsewill be assumed.
Function ReceiveCurrent([Transaction], [WantDestinationQueue],
[WantBody], [ReceiveTimeout], [WantConnectorType]) As
M SM QM essage
The ReceiveCurrentmetho d returns the c urrent message in the queue and remo ves it fro m the queue.
Transactionis an MSMQTransactiono bjec t o r o ne o f these values: MQ_NO_ TRANSACTION( 0) , whic h means that c all is no t part o f a transac tio n; MQ_MTS_ TRANSACTION( 1) , whic h means that the c all is made as part o f the c urrent MTS o r COM+ transac tio n; MQ_XA_TRANSACTION( 2) , whic h means that the c all is part o f an externally c o o rdinated, XA-c o mpliant transac tio n; o r MQ_SINGLE_MESSAGE
( 3) , whic h means that the c all retrieves a single message.
WantDestinationQueueis a Booleanwhen Truemeans that the MSMQ Message.DestinationQueueInfopro perty will be updated to c o ntain the info rmatio n abo ut the destinatio n queue. If no t spec ified, a value o f Falsewill be assumed.
WantBodyis a Booleanwhen Truemeans that the bo dy o f the message sho uld be returned ( default) . Set this value to Falseto reduc e the amo unt o f time to return the message.
ReceiveTimeoutis a Longc o ntaining the number o f millisec o nds that MSMQ will wait fo r a message to arrive.
WantConnecterTypeis a Booleanwhen Truemeans that c o nnec to r info rmatio n will also be retrieved. If no t spec ified, a value o f Falsewill be assumed.
Sub Reset( )
The Resetmetho d mo ves to the c urrent message c urso r to the start o f the queue.
The M SM QM essage Object
M SM QM essage object properties
Table 19-3 lists the pro perties o f the MSMQMessageo bjec t.Set not for the body of a message: Don’t use the Setstatem ent to assign an object to the Bodyproperty of an MSMQMessageobject. The Setstatem ent cre-ates a reference to an object. You should use an assignm ent statem ent to copy the entire contents of the object into the Bodyproperty.
Table 19-3
Properties of the M SM QM essage Object
Property Description
Ack A Longvalue that specifies the type of
acknow ledgem ent that is returned.
AdminQueueInfo An object reference to the MSMQQueueInfo
object that is used for acknow ledgem ent m essages.
AppSpecific A Longvalue containing application-specific inform ation.
ArrivalTime A Datevalue containing the date and tim e the m essage arrived at the queue.
AuthenticationProviderName A Stringvalue containing the nam e of the cryptographic provider used to generate the digital signature for the m essage.
AuthenticationProviderType A Longvalue containing the type of the cryptographic provider.
AuthLevel A Longvalue that specifies w hether or not the m essage should be authenticated w hen received.
Body A Variantvalue containing the m essage to be sent. Typically, this w ill be either a Stringor apersistent COM com ponent.
BodyLength A Longvalue containing the num ber of bytes in the m essage.
Class ALongvalue containing the type of m essage being sent.
Continued
Table 19-3
(continued)
Property Description
ConnectorTypeGUID A Stringvalue containing the GUID associated w ith the com ponent that w as used to externally set som e of the m essage properties that are typically set by M SMQ.
CorrelationId A Variantvalue containing a 20-byte
application-defined value that can be used to link m essages together.
Delivery Specifies how the m essage is delivered. Possible values are MQMSG_DELIVERY_EXPRESS(0), w hich is default and specifies a norm al delivery process w here it m ay be possible to lose the m essage in case of system failure; or MQMSG_ DELIVERY_RECOVERABLE(1), w hich m eans that a m ore reliable system is used.
DestinationQueueInfo An object reference to an MSMQQueueInfo
object that w ill be used as the destination queue.
DestinationSymmetricKey A Variantvalue containing the sym m etric key used to encrypt m essages.
EncryptAlgorithm A Long value, w hich specifies the encryption algorithm used to encrypt the body of the m essage.
Extension A Variantvalue containing additional application-specific inform ation associated w ith the m essage.
HashAlgorithm A Longvalue containing the hash algorithm used to authenticate a m essage.
Id A Variantvalue containing the identifier for this m essage. This value is autom atically generated by M SMQ.
IsAuthenticated An Integervalue that specifies w hether the local queue m anager authenticated the m essage.
IsFirstInTransaction An Integervalue that specifies w hether the m essage is the first m essage sent in a transaction.
Property Description
Journal A Longvalue that specifies w hether a copy of the m essage w as stored in the journal queue.
Label A Stringvalue containing an application-specific value describing the m essage.
MaxTimeToReachQueue A Longvalue containing the m axim um num ber of seconds that can elapse before the m essage m ust reach the queue before it w ill be canceled and an error m essage returned to the sender.
MaxTimeToReceive A Longvalue containing the m axim um num ber of seconds that can elapse before the m essage m ust be received before it w ill be canceled and an error m essage returned to the sender.
MsgClass A Longvalue containing the m essage type.
Priority A Longvalue containing the relative priority of the m essage.
PrivLevel A Longvalue containing how the m essage is encrypted.
ResponseQueueInfo An object reference to an MSMQQueueInfo
object that specifies the response queue used to send response inform ation.
SenderCertificate A Byte()array containing the security certificate inform ation.
SenderId A Byte()array containing the nam e of the user w ho sent the m essage.
SenderIdType A Longvalue that specifies w hether the
SenderIdvalue w as included in the m essage.
SenderVersion A Longvalue containing inform ation about the version of M SMQ that w as used to send the m essage.
SendTime A Datevalue containing the date and tim e the m essage w as sent.
Signature A Byte()containing the digital signature used to authenticate the m essage.
SourceMachineGuid A Stringarray value containing the GUID of the com puter, w hich sent the m essage.
Table 19-3
(continued)
Property Description
Trace A Longvalue that specifies w here a m essage w ill be returned to the sender in the report queue for each hop taken by the m essage in the delivery process.
TransactionId A Byte()array that identifies the transaction that sent the m essage.
TransactionStatusQueueInfo An object reference to a transaction status queue used for transactional m essages.
M SM QM essage object methods
The MSMQMessageo bjec t c o ntains metho ds fo r sending a message to a queue.
Sub AttachCurrentSecurityContext( )
The AttachCurrentSecurityContextmetho d retrieves the sec urity info rmatio n needed to attac h a c ertific ate to the message when requesting authentic atio n.
Sub Send(DestinationQueue As M SM QQueue, [Transaction])
The Sendmetho d transmits the message to the spec ified queue.DestinationQueueis an o bjec t referenc e to an o pen MSMQQueueo bjec t.
Transactionis a Variantwhic h c an be a referenc e to a MSMQTransactiono bjec t o r o ne o f these c o nstants: MQ_NO_TRANSACTION(0), whic h means that this c all isn’t part o f a transac tio n; MQ_MTS_TRANSACTION(1), whic h means that this c all is part o f the c urrent MTS o r COM+ transac tio n; MQ_XA_TRANSACTION, whic h means that this c all is part o f an externally c o o rdinated, XA-c o mpliant transac tio n; o r MQ_SINGLE_ TRANSACTION(3), whic h means the message c o mprises a single transac tio n.
M SM QEvent object events
The MSMQEvento bjec t is used to define the events in yo ur pro gram that will be fired when a message arrives in the queue. These events are defined by the
Event Arrived (Queue As Object, Cursor As Long)
The Arrivedevent is triggered when an MSMQMessageo bjec t arrives in the asso c i-ated queue.
Queueis an o bjec t referenc e to the queue c o ntaining the newly arrived message.
Cursoris a Longvalue fo r Cursoras spec ified in the EnableNotification
metho d.
It’s not automatic: You m ust call the EnableNotificationm ethod after pro-cessing the new ly arrived m essage in order to be notified w hen the next m essage arrives.
Event ArrivedError (Queue As Object, ErrorCode As Long,
Cursor As Long)
The ArrivedErrorevent is triggered when an erro r o c c urs.
Queueis an o bjec t referenc e to the queue c o ntaining the newly arrived message.
ErrorCodeis a Longvalue c o ntaining the c ause o f the erro r.
Cursoris a Long value fo r Cursoras spec ified in the EnableNotification
metho d.
Timeout for an error: The m ost com m on error returned in the ArrivedError event is a tim eout, w here no m essages w ere received in the specified am ount of tim e. As w ith the Arrivedevent, you m ust use the EnableNotificationm ethod again to receive the next event.
Accessing M essage Queues
While the o bjec t mo del fo r message queuing lo o ks c o mplic ated, it isn’t that diffic ult to master, espec ially if yo u use private queues. To demo nstrate message queuing, I built a pair o f pro grams. One o riginates requests, while the o ther respo nds to them. The c lient pro gram ( see Figure 19-5) retrieves info rmatio n abo ut a c usto mer, while the server pro gram ( see Figure 19-6) pro c esses the requests. I dec ided to use the COM+ transac tio n to get the info rmatio n bec ause it demo nstrates ho w the vario us piec es c an fit to gether into a ro bust applic atio n design.
Figure 19-5: Running the m essage queuing client
Figure 19-6: Running the m essage queuing server
Building the client program
The c lient pro gram is a relatively simple Visual Basic pro gram that c o mmunic ates with the server using two message queues. The first queue is the request queue, whic h is used to pass info rmatio n to the server, while the sec o nd queue is the respo nse queue, whic h is used to rec eive info rmatio n fro m the server.
Starting the client
Listing 19-1:
The Form_Load event in M SM Q Client
Private Sub Form_Load()
Set ReqInfo = New MSMQQueueInfo
ReqInfo.PathName = “.\Private$\VB6DB19Req”
Set ReqQueue = ReqInfo.Open(MQ_SEND_ACCESS, MQ_DENY_NONE) Set RespInfo = New MSMQQueueInfo
RespInfo.PathName = “.\Private$\VB6DB19Resp” Set RespQueue = RespInfo.Open(MQ_RECEIVE_ACCESS, _ MQ_DENY_RECEIVE_SHARE)
Set RespEvent = New MSMQEvent
RespQueue.EnableNotification RespEvent, , 1000 End Sub
When I o pen the request queue, I spec ify MQ_DENY_NONEto allo w o ther pro grams to share the request. Ho wever, when I o pen the respo nse queue, I do n’t permit anyo ne else to rec eive data fro m it by spec ifying MQ_DENY_RECEIVE_SHARE. In general, eac h user sho uld have their o wn unique respo nse queue. This permits the server to send info rmatio n to multiple users, even tho ugh the users may no t be aro und to rec eive the info rmatio n.
Onc e the respo nse queue is o pened, I c reate an MSMQEvento bjec t, who se Arrived
event will be fired when a message arrives in the respo nse queue. I use the Enable Notificationmetho d to asso c iate the Event o bjec t with the respo nse queue. I also spec ify a timeo ut value o f 1000 millisec o nds ( o r 1 sec o nd) . If no messages arrive in this amo unt o f time, the ArrivedErrorevent will be fired.
Requesting a customer’s information
After the user enters a Custo merId value and presses the Get Custo mer butto n, the
Command1_Clickevent will be triggered ( see Listing 19-2) . This ro utine verifies that a numeric value was entered into the Text1text bo x, and then c o nstruc ts and sends a message to the server.
I b egin b y c reating a new Customero b jec t and assigning the value o f the text b o x to the CustomerIdpro perty. Then I c reate a new MSMQMessageo b jec t. I set the
Listing 19-2:
The Command1_Click event in M SM Q Client
Private Sub Command1_Click() Dim msg As New MSMQMessage If IsNumeric(Text1.Text) Then
Set c = New Customer
c.CustomerId = CLng(Text1.Text) Set msg = New MSMQMessage
Set msg.ResponseQueueInfo = RespQueue.QueueInfo msg.Body = c
msg.Send ReqQueue End If
End Sub
The next statement is very c ritic al. Yo u must assign the o bjec t to the message’s
Bodypro perty. This saves a c o py o f the o bjec t in the Bodypro perty rather than merely saving a po inter to the o bjec t. Onc e yo u’ve po pulated the message, yo u c an use the Sendmetho d to plac e the message in a queue.
Set not: By now, if you see an assignm ent w ith an object on the right side of the equal sign (= ), you expect to see a Setstatem ent before the variable on the left side. If you try to use the Set statem ent w ith the Body property of a m essage, your inform ation w ill be lost as soon as the m essage is sent. Message queuing saves the persistent inform ation from an object and then destroys it. The persis-tent inform ation is then sent to the destination, w here it is recreated w hen the program receives the object.
Getting the results
Bec ause message queuing is async hro no us in nature, yo u do n’t kno w if the message will be returned in millisec o nds, sec o nds, ho urs, o r days. Thus, it is useful fo r an event to be fired when the message arrives. The Arrivedevent is triggered when a message is ready to be rec eived ( see Listing 19-3) . If no messages arrive befo re the timeo ut limit is reac hed, the ArrivedErrorevent will be fired ( see Listing 19-4) . The Arrivedevent begins by rec eiving the first message fro m the queue. The queue that the message arrives in is spec ified by the Queueparameter and the
Receivemetho d is used to retrieve the message. I spec ify a value o f 1000 milli-sec o nds to retrieve the message befo re returning an erro r.
Listing 19-3:
The RespEvent_Arrived event in M SM Q Client
Private Sub RespEvent_Arrived(ByVal Queue As Object, _ ByVal Cursor As Long)
Dim r As Customer Dim msg As MSMQMessage
Set msg = Queue.Receive(, , , 1000) If Not (msg Is Nothing) Then
Set r = msg.Body Text2.Text = r.Name Text3.Text = r.Street Text4.Text = r.City Text5.Text = r.State
Text6.Text = FormatNumber(r.Zip, 0) Text7.Text = r.Phone
Text8.Text = FormatDateTime(r.DateAdded, vbGeneralDate) Text9.Text = FormatDateTime(r.DateUpdated, vbGeneralDate) Check1.Value = CLng(r.MailingList) * -1
Text10.Text = r.Comments End If
RespQueue.EnableNotification RespEvent, , 1000 End Sub
Onc e I have the message, it is a very simple matter to get a referenc e to the
Customero bjec t fro m the Bodypro perty and assign its values to eac h o f the fields o n the fo rm.
What happened to all my requests?: When receiving m essages in the Arrived
event, it is possible to process the m essages too quickly. In this exam ple, I assum ed that the user w ould subm it one request at a tim e, but there is nothing to prevent the user from requesting inform ation on m ultiple custom ers before the response to the first m essage is received. If this happens, it is quite possible that the server w ill retrieve the next response before the user has finished view ing the first response. In this case, it m ay be useful to save the m essages into a
Collectionobject as they are received. Another approach w ould be to exam ine the inform ation in each response using the Peek m ethods, and only receive the m essage from the m essage queue w hen you’re ready to delete it.
Befo re I leave this event, I need to reset the trigger so that the next message is rec eived. This is do ne using the same EnableNotificationmetho d that I o rigi-nally used to enable this event.
But it worked once:If you can receive the first m essage, but your program does-n’t process any other m essages after that, verify that you re-enabled the response event after processing a m essage.
The ArrivedErrorevent is fired when a message do esn’t arrive in the message queue befo re its timeo ut value. If yo u are expec ting a steady stream o f messages, yo u may want to re-enable the event in the ArrivedErrorevent ( see Listing 19-4) .
Listing 19-4:
The RespEvent_ArrivedError event
in M SM Q Client
Private Sub RespEvent_ArrivedError(ByVal Queue As Object, _ ByVal ErrorCode As Long, ByVal Cursor As Long)
RespQueue.EnableNotification RespEvent, , 1000 End Sub
Building the server program
The server pro gram is designed to rec eive requests fro m a c lient in the request queue, c all the GetCustomertransac tio n I wro te in Chapter 18, and return the data to the c lient in the respo nse queue. It also inc ludes to o ls to c reate and delete the queues that the c lient pro gram will use.
Creating queues
When the user presses the Build Queues butto n, the Command1_Clickevent will be triggered ( see Listing 19-5) . Fo r eac h queue, this ro utine c reates a new QueueInfo
o bjec t, spec ifies the PathNameo f the queue, and then c alls the Createmetho d to define the queue.
Deleting is simple:To delete a queue, use the sam e logic as show n in Listing 19-5, but substitute Deletefor Create.
Listing 19-5:
The Command1_Click event in M SM Q Server
Private Sub Command1_Click() Dim RespInfo As MSMQQueueInfo Set RespInfo = New MSMQQueueInfo
RespInfo.PathName = “.\Private$\VB6DB19Resp” RespInfo.Create
Set ReqInfo = New MSMQQueueInfo
ReqInfo.PathName = “.\Private$\VB6DB19Req” ReqInfo.Create
Set respinfo = Nothing Set ReqInfo = Nothing End Sub
Starting the server
The server will no t pro c ess any messages until the user presses the Run Server but-to n. This triggers the Command2_Clickevent, as sho wn in Listing 19-6. This ro utine begins by writing that the server is ac tive to the text bo x o n the fo rm, and then it o pens the request queue and enables no tific atio n using the ReqEvento bjec t. At this po int, the server will respo nd to messages as they are sent, using the ReqEvent_ Arrivalevents.
Listing 19-6:
The Command2_Click event in M SM Q Server
Private Sub Command2_Click()
Text1.Text = FormatDateTime(Now, vbGeneralDate) & _ “ Server active.” & vbCrLf
Set ReqInfo = New MSMQQueueInfo
ReqInfo.PathName = “.\Private$\VB6DB19Req” Set ReqQueue = ReqInfo.Open(MQ_RECEIVE_ACCESS, MQ_DENY_RECEIVE_SHARE)
Set ReqEvent = New MSMQEvent
Processing messages
The heart o f the server is the ReqEvent_Arrivedevent ( see Listing 19-7) . This event is respo nsible fo r rec eiving the request, c alling the COM+ transac tio n, and returning the data to the user via the respo nse queue. This ro utine begins by appending an entry to the text bo x with the date and time that the message was rec eived. This info rmatio n is useful in mo nito ring the server’s ac tivities while test-ing the pro gram, tho ugh it sho uld be eliminated in a pro duc tio n applic atio n.
Listing 19-7:
The ReqEvent_Arrival event in M SM Q Server
Private Sub ReqEvent_Arrived(ByVal Queue As Object, _ ByVal Cursor As Long)
Dim c As Customer
Dim ci As CustInfo.CustomerInfo Dim msg As MSMQMessage
Dim xc As Customer Dim xmsg As MSMQMessage Dim xqueue As MSMQQueue
Text1.Text = Text1.Text & FormatDateTime(Now, vbGeneralDate) _ & “ Message received.” & vbCrLf
Set msg = Queue.Receive(, , , 1000) If Not (msg Is Nothing) Then
Set c = msg.Body
Set ci = CreateObject(“CustInfo.CustomerInfo”) Set xc = ci.GetCustomer(c.CustomerId)
Set ci = Nothing
Set xmsg = New MSMQMessage xmsg.Body = xc
Set xqueue = msg.ResponseQueueInfo.Open(MQ_SEND_ACCESS, _ MQ_DENY_NONE)
xmsg.Send xqueue Set xqueue = Nothing Set xc = Nothing End If
Next, I rec eive the message using the Queueparameter. Onc e I have the message, I c an extrac t the CustomerIdvalue fro m the message’s bo dy and c all the CustInfo. CustomerInfotransac tio n to get the requested info rmatio n. Then I c reate a new
MSMQMessageo bjec t and save the Customero bjec t into the Bodypro perty. No te that I didn’t use a Setstatement, sinc e I want a c o py o f the do c ument rather than a referenc e fo r the o bjec t.
To send the message, I o pen the respo nse queue c o ntained in the o riginal message and use the Sendmetho d to put the message into the respo nse queue. Then I reset the message no tific atio n so that the next time a message arrives, I will be ready to pro c ess it. The pro gram also inc ludes a ReqEvent_ArrivedErrorsimilar to the o ne used in the MSMQ Client pro gram to allo w the server to c o ntinue to rec eive messages after a timeo ut c o nditio n.
Viewing M essage Queue Information
Yo u may find it useful to have an independent to o l to see messages as they arrive in a message queue fo r pro c essing. If yo u are running Windo ws 2000 Server, yo u c an use the Co mputer Management utility ( Start➪Pro grams➪Administrative To o ls➪
Co mputer Management) to examine the c o ntents o f a message queue.
After starting this pro gram, yo u’ll see the typic al Mic ro so ft Management Co nso le with a tree o f ic o ns o n the left side with details abo ut the c urrently selec ted ic o n o n the right ( see Figure 19-7) . By expanding the Servic es and Applic atio ns ic o n, yo u c an expo se the Message Queuing ic o n. Then by drilling do wn, under Private Queues, yo u c an see the queues that are used by the MSMQ Client and MSMQ Server pro grams.
Within eac h queue, yo u c an selec t Queue messages to see the messages that are in the queue waiting to be pro c essed. The easiest way to try this, using the sample pro grams fro m this c hapter, is to run the c lient pro gram witho ut running the server. Any messages sent fro m the c lient pro gram will ac c umulate in the queue, and if yo u then run the server pro gram, yo u c an see the messages quic kly disappear — returned to the c lient pro gram via the respo nse queue.
Where did my message go?: If your program isn’t w orking properly, this utility w ill help you discover w hether or not the program is sending the m essages properly.
Figure 19-7: Running the Com puter Managem ent utility
Thoughts on M essage Queuing
This chapter is just a brief introduction to w hat you can do w ith m essage queuing. I find m essage queuing a fascinating tool that m akes it easy to im plem ent asynchronous pro-cessing.
Consider this exam ple. You have a group of salespeople out in the field w ith laptop com -puters. Since it’s not practical for them to stay in constant contact w ith the hom e office, you build a stand-alone application that keeps track of the item s in the sales catalog and allow s them to enter orders that can be printed out and subm itted later.
If you w ere to include m essage queuing in the application, you could m odify the applica-tion so that it autom atically queues orders to be sent to the hom e office the next tim e the salesperson connects to the organization’s netw ork. The application could also receive updates to the local sales database, as w ell as updates to custom er orders that have already been placed.
Summary
In this c hapter yo u learned the fo llo wing:
✦Yo u c an use the Mic ro so ft Message Queuing to send info rmatio n asyn-c hro no usly fro m o ne asyn-c o mputer to ano ther.
✦Yo u c an use message queues to smo o th the wo rklo ad in a heavily lo aded server.
✦Yo u c an use public queues o nly o n Windo ws 2000 servers, while private queues c an be used o n Windo ws 98 and NT as well as Windo ws 2000.
✦Yo u c an o pen a queue with the MSMQQueueInfoo bjec t.
✦Yo u c an send messages using the MSMQQueueo bjec t.
✦Yo u c an rec eive messages via the MSMQEvento bjec t.
✦Yo u c an view the messages in a message queue by using the Co mputer Management utility to verify if yo ur applic atio n is pro perly sending messages.