Flylib.com

Books Software

 
 
 

Receiving Results


Receiving Results

With the current version of the sample application, the sending application never knows if the message is ever dealt with. To get results from the receiver, acknowledgement queues or response queues can be used.

Acknowledgement Queues

With an acknowledgement queue, the sending application can get information about the status of the message. With the acknowledgements you can define if you would like to receive an answer, if everything went OK, or if something went wrong. For example, acknowledgements can be sent when the message reaches the destination queue or when the message is read or if it didn't reach the destination queue or was not read before a timeout elapsed.

In the example the AdministrationQueue of the Message class is set to the CourseOrderAck queue. This queue must be created similar to a normal queue. This queue is just used the other way around: the original sender receives acknowledgements. The AcknowledgementType property is set to AcknowledgementTypes.FullReceive to get an acknowledgement when the message is read:


Message message = new Message(order);


message.AdministrationQueue =


new MessageQueue(@".\CourseOrderAck");


message.AcknowledgementType = AcknowledgementTypes.FullReceive;


queue.Send(message, "Course Order {" +


order.Customer.Company + "}");


string id = message.Id;

The correlation id is used to determine what acknowledgement message belongs to which message sent. Every message that is sent has an id, and the acknowledgement message that is sent in response to that message holds the id of the originating message as its correlation id. The messages from the acknowledgement queue can be read using MessageQueue.ReceiveByCorrelationId() to receive the associated acknowledgement.

Instead of using acknowledgements, the dead-letter queue can be used for messages that didn't arrive at their destination. By setting the UseDeadLetterQueue property of the Message class to true , the message is copied to the dead-letter queue if it didn't arrive at the target queue before the timeout was reached.

Timeouts can be set with the Message properties TimeToReachQueue and TimeToBeReceived .

Response Queues

If more information than an acknowledgement is needed from the receiving application, a response queue can be used. A response queue is like a normal queue, but the original sender uses the queue as a receiver and the original receiver uses the response queue as a sender.

The sender must assign the response queue with the ResponseQueue property of the Message class. The sample code here shows how the receiver uses the response queue to return a response message. With the response message responseMessage the property CorrelationId is set to the id of the original message. This way the client application knows what message the answer belongs to. This is similar to acknowledgement queues. The response message is sent with the Send() method of the MessageQueue object that is returned from the ResponseQueue property:


public void ReceiveMessage(Message message)


{


Message responseMessage = new Message("response");


responseMessage.CorrelationId = message.Id;


message.ReesponseQueue.Send(responseMessage);


}



Transactional Queues

With recoverable messages it is not guaranteed that the message will arrive in order and just once. Failures on the network can cause messages to arrive multiple times; this happens also if both the sender and receiver have multiple network protocols installed that are used by Message Queuing.

Transactional queues can be used where these guarantees are required:

  • Messages arrive in the same order they have been sent

  • Messages arrive only once

With transactional queues, a single transaction doesn't span the sending and receiving of messages. The nature of Message Queuing is that the time between send and receive can be quite long. In contrast, transactions should be short. With Message Queuing the first transaction is used to send the message into the queue, the second transaction forwards the message on the network, and the third transaction is used to receive the messages.

The next example shows how to create a transactional message queue and how to send messages using a transaction.

A transactional message queue is created by passing true with the second parameter of the MessageQueue.Create() method.

If you would like to write multiple messages to a queue within a single transaction, you have to instantiate a MessageQueueTransaction object and invoke the Begin() method. When you are finished with sending all messages that belong to the transaction, the Commit() method of the MessageQueueTransaction object must be called. To cancel a transaction (and no messages are written to the queue), the Abort() method must be called as you can see within the catch block:

using System; using System.Messaging; namespace Wrox.ProCSharp.Messaging { class Program { static void Main(string[] args) {

if (!MessageQueue.Exists(@".\MyTransactionalQueue"))


{


MessageQueue.Create(@".\MyTransactionalQueue", true);


}


MessageQueue queue = new MessageQueue(@".\MyTransactionalQueue");


MessageQueueTransaction transaction =


new MessageQueueTransaction();


try


{


transaction.Begin();


queue.Send("a", transaction);


queue.Send("b", transaction);


queue.Send("c", transaction);


transaction.Commit();


}


catch


{


transaction.Abort();


}

} } }