Sending and Serializing Messages

   

A message in Microsoft Windows Message Queuing consists of a body and a set of properties. Message bodies can contain text or any form of binary information, and can be encrypted. A message, including its body and all specified properties, cannot be bigger than 4MB in size .

You can create and send messages with your MessageQueue components . Messages created in your applications can be sent to any public, private, journal, dead-letter, or transactional queue.

Sending Simple Messages

Using an instance of the MessageQueue component, you can send simple messages to a queue in as little as two lines of code. When you send a simple message, you must perform the following actions:

  1. Create a connection to the queue to which you want to send a message.

  2. Specify the appropriate formatter for the data you want to send. The formatter controls what type of data can be sent in a message and how that data is persisted . In simple cases, the default formatter is acceptable.

  3. Call the MessageQueue.Send method, passing the object to be sent.

After you decide with which queue you want to communicate, you need to create an instance of the MessageQueue component that references the queue you want to use. Use the component's Path property to connect to the queue with which you want to communicate by the queue path, format name , or label.

Each MessageQueue component contains a series of default properties that are applied to all messages that component sends, unless you specify otherwise in an individual message. In the simplest scenario, you can send a simple message to the queue using the default properties set for the component.

You use the Send method to specify a message and send it to the queue. You can send objects, primitive data types, streams, and other kinds of data in a simple message.

The MessageQueue component takes the data you specify in the Send method's argument, persists it into a message, and sends the message to the specified queue.

You can also use the Message object to send far more complex messages to a queue. In addition, you can send messages as part of a transaction.

Set the appropriate value for the Formatter property for your component.

Use the Send method to send a simple message to your queue, specifying the message as an argument of the method.

Your code to send a simple message might look like this:

 ' Visual Basic  ' Create a connection to the queue.  Dim MessageQueue1 as New System.Messaging.MessageQueue     ("YourMachine\YourQueue")  ' Send an integer.  MessageQueue1.Send(1)  ' Send a string.  MessageQueue1.Send("Hello world")  // C#  // Create a connection to the queue.  MessageQueue mq = new System.Messaging.MessageQueue (@"YourMachine\YourQueue");  // Send an integer.  mq.Send (1);  // Send a string.  mq.Send ("Hello world"); 

Sending Complex Messages

In addition to sending a simple message by specifying your message in the Send method's argument, you can gain more control over your messages by explicitly creating a Message object, rather than letting the shared Send method create and send one for you. By manipulating the properties of the resulting Message object, you can create more complex messages and exert more control over the way your messages are handled.

When you send a complex message, you must first create a connection to the queue with which you want to communicate, and then specify the data you want to send. However, as part of specifying the data to send, you create an instance of the Message class, set the properties you need, and fine-tune the delivery mechanisms before sending your message. As with simple messages, the system persists your message object and sends it to the queue you specified.

To use the Message class to send a complex message, do the following:

  1. Create an instance of the MessageQueue component and set its Path property to the queue to which you want to refer.

  2. Create an instance of the Message object.

  3. Set the body of the message and specify any properties you want to change from their default values.

  4. Use the Send method to send your object to the queue.

When you are finished, your code might look like this:

 ' Visual Basic  Dim myMQ1 as New System.Messaging.MessageQueue (".\YourQueue")  Dim newMessage as System.Messaging.Message("Hello again")  newMessage.Label = "This is the label"  MessageQueue1.Send(newMessage)  // C#  MessageQueue MyMQ1 = new MessageQueue (@".\YourQueue");  System.Messaging.Message newMessage =    new System.Messaging.Message("Hello again");  newMessage.Label = "This is the label";  MyMQ1.Send (newMessage); 

Sending Messages to Disconnected Queues

There are two situations in which messages cannot readily be delivered to their queues: when the machine on which the queue resides is not available, and when the domain controller needed to route your message is not available. Message Queuing enables you to handle these situations so that if you are disconnected from the network, or a necessary machine or controller is not available, you can continue to send messages. In these cases, the messages are temporarily stored on a queue on the local machine or a machine along the delivery route until either you or the necessary resources are back online.

For example, suppose you have a central queue that records orders sent by your on-the-road sales force. Members of the sales force work in disconnected mode much of the day, recording order information from customer sites, and dial in once a day to transfer all this information to the central queue. Because messages can be sent to queues when the sender is disconnected, salespeople can send messages immediately upon recording the customer's information, and the system caches those messages until the nightly call is placed.

Sending a message to a disconnected queue is almost identical to the process of sending a message to an available queue. You do not have to perform any special configuration for your component to store messages in a temporary queue when the queue to which you are sending is not available. You must be aware of two main differences:

  • If the queue is unavailable but the domain controller is working, you must identify the queue to which you want to send by the queue's format name, rather than by the path name. When a queue is disconnected, the domain controller for the queue cannot resolve the path name correctly.

  • If you set a time-out interval on your message send operation, the time-out period begins to count down as soon as the message is sent. This means that while the message sits on your local machine waiting for the queue to become available, the timeout period is active and the expiration time is approaching. If you want to use the time-out period, you must either set it to a large enough interval to allow for delivery or request negative acknowledgement for the message so you know whether expiration has occurred.

To send a message to a disconnected queue, do the following:

  1. Create an instance of the MessageQueue component.

  2. Set the Path property for the component to the format name of the queue to which you want to send a message.

  3. Send your message normally.

Message Acknowledgement

You can set up your MessageQueue component to generate acknowledgement messages that tell you whether the message was successfully delivered. You can receive two main types of acknowledgement:

  • Acknowledgement that the message reached its destination queue.

  • Acknowledgement that the destination application retrieved the message from the queue.

Within each of these scenarios, you also can receive positive or negative acknowledgement. In positive acknowledgement, you receive an acknowledgement message when your message successfully reaches its destination queue or application. In negative acknowledgement, you receive an acknowledgement message when your message fails to reach its destination queue or application. A message might fail to reach its destination if its time-out period expires or if the message cannot be authenticated.

As with most operations in Message Queuing, acknowledgements are handled via sending a new message to a queue. In this case, the acknowledgement message is sent from the target queue to a special type of queue called an Administration queue. Acknowledgement messages differ from standard messages in that they contain no attached body; only the information in the message header is of interest in an acknowledgement.

Acknowledgement messages for your application are sent to whatever queue you specify in the AdministrationQueue property, either in the DefaultPropertiestoSend class for your component instance or on the Message object. You determine the type of acknowledgement you want to receive by setting the AcknowledgeType property to one of its predetermined values.

You can check acknowledgement messages in the same way you check any message on a queue: by peeking at the acknowledgement queue or removing messages from it.

Requesting Acknowledgement for Messages

You can request positive acknowledgement, negative acknowledgement, or a combination of acknowledgement types on the messages your MessageQueue components sends.

To request acknowledgement of a message, do the following:

  1. Create an instance of the MessageQueue component and set its Path property to the queue you want to reference.

  2. Create the message you want to send.

  3. Set the AdministrationQueue property for your Message object to the queue to which you want acknowledgement messages sent.

  4. Set the Message object's AcknowledgeType property in the DefaultPropertiestoSend grouping to the appropriate value.

Table 23.1 shows how to determine the acknowledgement responses.

Table 23.1. MessageQueue Response Acknowledgements

Type

Description

FullReachQueue

Acknowledgementwhen a message reaches or fails to reach the queue to which it was sent.

FullReceive

Acknowledgementwhen the message reaches or fails to be retrieved from the queue before its time-to-be-received timer expires. Note that the Queue Manager, rather than the destination application, generates this acknowledgement.

NegativeReceive

Request negative acknowledgment when a message fails to be retrieved from the queue.

NotAcknowledgeReachQueue

Acknowledgementonly if a message you send fails to reach the queue.

NotAcknowledgeReceive

Acknowledgementonly if the destination application could not retrieve a message you sent.

PositiveArrival

Positiveacknowledgment when the message reaches its queue.

PositiveReceive

Positive acknowledgment when the message is successfully retrieved from the queue.

AdministrationQueue

Send the message, and then check the queue you specified for the appropriate acknowledgement.

None

Preventacknowledgement messages from being sent.

Message Queue Journal Storage

Journal queues enable you to save copies of messages as they are processed . You can store copies of the messages you send from your computer in the local machine journal queue, or you can store copies of messages removed from a queue in that queue's journal on the server.

Journal storage can be useful if you need to resend a message at a later point. For example, suppose you send a message to a queue and then receive negative acknowledgement, reporting that it could not be delivered. Acknowledgement messages do not contain the body of the original message; instead, they give you some header information and a correlation ID that corresponds to the original message. If you have journal recording turned on, you can use this correlation ID to locate the original message in your machine's journal queue, recreate the message object, and resend it.

You can use the ReceivebyCorrelationID or the PeekbyCorrelationID methods to retrieve a message by its correlation ID. Note that several messages may have the same correlation ID, and these methods retrieve the first message in the queue with the given ID.

You should note a few caveats about journal queues:

  • There is one global journal queue per machine. All messages sent from that machine are recorded in that journal queue, whether they are delivered successfully or not. In addition, each queue has its own associated journal queue.

  • Two properties control how journals are used. If you set the UseJournalQueue on the MessageQueue object, you enable journal storage for any messages that queue receives, not messages sent with that object. The messages sent with the queue are placed in the queue journal. If you set the UseJournalQueue on the Message object, you enable system journal storage; this means that messages sent from your system are placed in the sender's system queue.

  • Journal queues have a maximum size, called a quota . This size is limited by the disk capacity of the computer on which the queue resides. After the queue capacity is reached, messages that would have been sent to the journal queue are no longer saved in the system. No errors are raised when this occurs. It is important that you periodically purge your journal queues to prevent this from occurring.

  • Journal queues are silent, or in other words, they cannot create acknowledgement messages of their own, send removed messages to dead-letter queues, or process time-outs.

Storing Messages in Journal Queues

You can set up the use of journal queues for sent messages in either of two ways: You can set a default property for your MessageQueue component so that all messages sent by it will use journals, or you can establish journal queue recording for individual messages you send.

To use journals for all messages sent by an instance of the MessageQueue component, do the following:

  1. Create an instance of the MessageQueue component and set its Path property to the queue to which you want to refer.

  2. Set the UseJournalQueue property on the DefaultPropertiestoSend class for your component to True.

To set journal recording for an individual message, do the following:

  1. Create the message you want to send.

  2. In code, set the UseJournalQueue property to True.

Your code might look like this:

 ' Visual Basic  Message1.UseJournalQueue = True  // C#  Message1.UseJournalQueue = true; 

To set journal recording for messages removed from a queue, do the following:

  1. Create an instance of the MessageQueue component and set its Path property to the queue to which you want to refer.

  2. Set the UseJournalQueue property for the MessageQueue component that references that queue to True.

Your code might look like this:

 ' Visual Basic  MessageQueue1.UseJournalQueue = True  // C#  MessageQueue1.UseJournalQueue = true; 

To set the maximum size for a journal queue, do the following:

  1. Create an instance of the MessageQueue component and set its Path property to the journal queue you want to refer to.

  2. Set the MaximumJournalSize property to the capacity, in kilobytes, that you want to use for your journal queue.

Default Message Properties

When you create an instance of the MessageQueue component, you have the option of setting a series of default properties that messages sent by that component will use. This saves you time spent defining your messages, and gives you more control over the Send method without requiring you to create and configure Message objects.

Only messages that are not sent with the Message object use the DefaultPropertiestoSend values. When you send a message using the Message object, the properties of the Message object are used.

You set default message properties by setting values for the properties in the DefaultPropertiestoSend class. These default properties control features such as whether acknowledgement messages are generated and where they are sent, how your messages are encrypted and authenticated, the message priority, and the time-out period for your messages.

Message Priority

Setting a default priority for your messages affects the order in which they are sent to their destination queues. You set the Priority property to determine the default priority for messages your component sends. Priority ratings default to normal, with settings for lower and higher priorities.

The priority setting for a message determines where the message is placed in the queue. Messages sent with a higher priority are placed higher in the queue, and messages with a lower priority are placed lower in the queue. When the queue receives a set of messages with an identical priority setting, the messages are arranged in the queue according to the time when they were sent.

You cannot set priority on messages that are being sent to transactional queues, because the transaction itself determines the order in which messages are processed on transactional queues.

Acknowledgement and Response Properties

You can set several default properties that determine whether responses and acknowledgements will be generated for your component's messages and how these responses will be handled. The properties you can set as a default for all messaging operations include

  • The AcknowledgeType property and the AdministrationQueue properties, which you can use to determine whether acknowledgement messages should be generated when your messages reach or fail to reach their destination queue, or when the target application retrieves messages from the queue.

  • The ResponseQueue property, which you can use to indicate the return path for any messages that will be sent by the application retrieving your messages from the queue. These messages differ from acknowledgement messages in that the destination application, rather than the Queue Manager, generates them.

You can determine whether copies of your outgoing messages should be stored in a journal queue by setting the UseJournalQueue property and, similarly, whether undeliverable messages should be sent to a dead-letter queue by setting the UseDeadLetterQueue property.

Time-Out Properties

You can use two time- related properties to maintain better control of your messages. Both properties determine how long a message can exist in the system before it is discarded. You use the TimeToReachQueue property to specify how long a message has to try to reach its destination queue. You use the TimeToBeReceived property to specify how long the message should remain in the system, from the time it is sent until the time the destination application removes it from the queue. If either timer interval expires, Message Queuing discards the message.

When a message is discarded because of an expired timer, the Queue Manager might take additional steps:

  • If you set the UseDeadLetterQueue property to True, a copy of the discarded message is sent to the specified dead-letter queue.

  • If you set the AcknowledgeType property to send negative acknowledgements, an acknowledgement message is sent to the specified Administration queue.

By default, no time-out interval is set for either property. If you set a value for both properties, the value in the TimeToBeReceived property takes precedence.

Message Serialization

Serialization is the process of taking objects and converting their state information into a form that can be stored or transported. The basic idea of serialization is that an object writes its current state, usually indicated by the value of its member variables , to persistent storage. Later, the object can be re-created when the object's state is read, or deserialized, from the storage. Serialization handles all the details of object pointers and circular object references that are used when you serialize an object.

In the message-queuing feature, serialization refers specifically to the process of converting an object or set of data into a message that can be sent to a queue, and then converting messages retrieved from the queue back into objects or data that your application can process.

A Formatter object handles message serialization in your Visual Studio .NET or .NET framework applications. When a message is sent to the queue, the formatter serializes an object into a stream that can be sent to the message queue. When reading from a queue, the formatter deserializes the message data into the Body property.

You choose the appropriate type of formatter for the kind of data you want to send and receive. Visual Studio and the .NET framework ship three predefined formatters, each designed to persist and de-persist a different type of data:

  • The XMLMessageFormatter object uses human-readable XML strings to persist objects and primitive data types into and out of messages. This is the default formatter setting for MessageQueue components.

  • The BinaryMessageFormatter object persists one or more connected objects into serialized streams. The result is very compact and fast to parse, but not human-readable.

  • The ActiveXMessageFormatter object persists primitive data types, allowing for interoperability with components that use previous versions of Message Queuing. The resulting serialization is very compact. This formatter is designed with Windows in mind and does not produce human-readable results. However, it is an extremely fast method of serialization.

By default, an XMLMessageFormatter is created for you when you create a MessageQueue component instance and it is associated with the instance. When the Send method is called on the MessageQueue instance, the body of your message is serialized using this formatter. You do not have to write any additional code to use the formatter during a send operation.

Reading a message is slightly more complex. To use a formatter to read from the queue, you must set properties indicating how the body of the message should be handled. If you are using the XMLMessageFormatter object, you set the TargetTypes or TargetTypeNames property. If you are using the BinaryMessageFormatter object, you set a different series of properties. The ActiveXMessageFormatter object has no associated properties.

In addition to using the formatters shipped with Visual Studio and the .NET framework, you can create your own formatters if you need to work with different types of data. You can import your formatter into a project and access it in code.

You choose the formatter you want to use by setting the Formatter property for the queue, message, or MessageQueue component with which you are working.

One advantage of the XML formatter is that you can read the strings that are created when the object or data is serialized. This means that if something happens and the message cannot be de-persisted from the message queue, you can take a look at the message itself and usually fix the problem.

Another advantage is that messages serialized with this formatter do not have to be deserialized by the same Formatter object. That is, you do not need to have the same formatter class in the receiver as you do in the sender, as long as both parties know the data schema. In addition, messages serialized by the XML formatter do not necessarily have to be deserialized at all. Most browsers and other XML viewers can parse XML messages.

   


Special Edition Using ASP. NET
Special Edition Using ASP.Net
ISBN: 0789725606
EAN: 2147483647
Year: 2002
Pages: 233

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net