This sample demonstrates how to use the Windows Azure Service Bus and the messaging "dead letter queue" functionality.
The sample shows a simple sender and receiver communicating via a Service Bus queue. Both sender and receiver prompt for service namespace credentials. (These are used to authenticate with the Access Control service, and acquire an access token that proves to the Service Bus insfrastructure that the client is authorized to access the queue.) The sender creates the queue, and sends messages simulating different orders into it. The receiver reads orders until the queue is empty, simulating failure on processing some messages. The failing messages are dead-lettered. At the end of the samples, the dead-lettered messages are received and logged.
It is also possible to create a separate receiver application for reading the messages in the dead letter queue, and performing additional actions for each message (such as updating order types to include these unknown orders).
Note: Dead-lettering also applies to topics and subscriptions, where each subscription has its own dead letter subqueue. It can be accessed in a similar way to a subscription's dead letter subqueue: subscriptionClient.CreateReceiver("$DeadLetterQueue"). |
Prerequisites
If you haven't already done so, please read the release notes document that explains how to sign up for a Windows Azure account and how to configure your environment.
Sender
The sender's flow:
- Obtains user credentials and creates a NamespaceManager (namespaceClient) and a MessagingFactory (messagingFactory). These entities hold the credentials and are used for all messaging management and runtime operations.
- Creates queue using the namespaceClient
- Sends messages to queue
- Waits for user input to delete queue
Note: The static
ServiceBusEnvironment.CreateServiceUri
function is provided to help construct the URI with the correct format and
domain name. It is strongly recommended that you use this function instead of
building the URI from scratch because the URI construction logic and format
might change in future releases. |
Receiver
The receiver's flow:
- Gets user credentials, but only creates a MessagingFactory and a QueueClient (for runtime operations), since the queue was created by the sender
- Receives messages from the queue and processes them.
- Processing simulates an error by failing to process random messages for MaxRetryCount times. Once a message cannot be processed MaxRetryCount times, the message is dead-lettered.
- Reads and logs messages from the dead-letter queue (separate dead-letter queue message receiver created)
Note: Messages can only be dead-lettered if they have been received using the PeekLock receive mode. In comparison to the simpler ReceiveAndDeleted mode (message deleted on receiving), the PeekLock mode requires a message to either be completed (Complete()) to take the message out of the queue. If a PeekLock receiver calls Abandon() on a message, or does not Abandon() or Complete() with the message lock timeout, the message will be made available on the queue, for processing by any receiver. |
Running the Sample
To run the sample, build the solution in Visual Studio or from the command line, then run the two resulting executable files. Start the sender first, then start the receiver. Once the receiver has completed, close the sender to clean up the messaging entities. Both programs prompt for your service namespace and the issuer credentials. For the issuer secret, be sure to use the "Default Key" value from the portal, rather than one of the management keys.
Note that the expected output below is a sample only - it may not exactly match your run because the sample randomly decides which messages should be dead-lettered.
Expected Output - Sender
Please provide the namespace to use: <service namespace> Please provide the Issuer name to use: <issuer name> Please provide the Issuer key to use: <issuer secret> Creating queue 'OrdersService'... Sending messages to queue... Sending message of order type DeliveryOrder. Sending message of order type StayInOrder. Sending message of order type TakeOutOrder. Sending message of order type TakeOutOrder. Sending message of order type DeliveryOrder. Press [Enter] to delete queue and exit. |
Expected Output - Receiver
Please provide the namespace to use: <service namespace> Please provide the Issuer name to use: <issuer name> Please provide the Issuer key to use: <issuer secret> Reading messages from queue... Adding Order 1 with 10 number of items and 15 total to DeadLetter queue Received Order 2 with 15 number of items and 500 total Adding Order 3 with 1 number of items and 25 total to DeadLetter queue Adding Order 5 with 3 number of items and 25 total to DeadLetter queue Received Order 4 with 100 number of items and 100000 total No more messages left in queue. Logging dead lettered messages... Order 1 with 10 number of items and 15 total logged from DeadLetter queue. DeadLettering Reason is "UnableToProcess" and Deadlettering error description is "Failed to process in reasonable attempts" Order 3 with 1 number of items and 25 total logged from DeadLetter queue. DeadLettering Reason is "UnableToProcess" and Deadlettering error description is "Failed to process in reasonable attempts" Order 5 with 3 number of items and 25 total logged from DeadLetter queue. DeadLettering Reason is "UnableToProcess" and Deadlettering error description is "Failed to process in reasonable attempts" Press [Enter] to exit. |