Design Patterns for MOM Applications

One of the ways of reducing the difficulty of designing MOM-based applications is to employ design patterns. These are standard applications scenarios, that are commonly encountered, for which standard design techniques have already been developed. Design patterns sometimes supply the complete solution for an application. If not, they can at least provide a starting point to a more sophisticated design.

Most MOM applications tend to follow a small number of patterns. These patterns allow quick decisions to be made on which product features to use. Without these design patterns, the choice can be overwhelming. These patterns also define how specific messaging errors have to be handled.

The design patterns that we will be looking into in this section are:

  • The Observer design pattern

  • Pseudo-synchronous inquiry-style applications

  • Fire-and-forget update-style applications

  • Asynchronous inquiry-style applications

  • Pseudo-synchronous update-style applications

  • Asynchronous update-style applications with acknowledgement

These six design patterns can be used to create completely functional MOM Applications, or at least major functional components of larger MOM applications. It is also possible to use several patterns in the same MOM application, each providing one major function. The first one is for the Publish/Subscribe messaging domain. The other five are for the Point-to-Point messaging domains.

The Observer (Publish/Subscribe) Design Pattern

The Observer pattern is used to notify dependent observer (subscriber) objects that state information has changed in the subject (topic). The intent is to define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

The object interaction diagram for the Observer design pattern is shown in the figure below:

click to expand

The Observer objects are dependent on the Subject object and therefore should be notified of any change in its state. There's no reason, to limit the number of objects to two — there may be any number of Observers for the same subject.

The Observer pattern, also known as the Publish/Subscribe or the Dependents pattern, describes how to establish these relationships. All observers are notified whenever the subject undergoes a change in state. In response, each observer synchronizes its state with the subject's state. The subject is the publisher of notifications. It sends out these notifications without having to know who its observers are. Any number of observers can subscribe to receive notifications.

The Observer design pattern can be used in any of the following situations:

  • When an abstraction contains two components, one of which needs notification of something, but the other of which doesn't need to know that the notification has been processed. Observing is a process in which the observed doesn't need to know who is observing it, or why. Encapsulating these aspects in separate objects lets you vary and reuse them independently.

  • When a change to one object requires changing others, and you don't know how many objects need to be changed.

  • When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.

Pseudo-Synchronous Inquiry-Style Applications

In any inquiry application, a client program requests information from a server. Often, the client cannot continue until it received the information that it requested. The figure below captures this synchronous request behavior where a sender sends a request to the receiver. On the receiver end, the request message is first read, and then processed before a reply is sent to the original sender. The Sender waits for the reply to come back from the receiver before moving on with other operations and is, in essence, being blocked till the call returns. This is similar to how traditional synchronous RFC calls work. This is therefore a request-reply pattern:

click to expand

This design pattern has a couple of important characteristics:

  • Firstly, it is synchronous at the client end. The client-side implementation will not return control until either the result is available, or the operation has failed.

  • Secondly, this is an inquiry pattern. Data at the server is not affected by running this implementation. The operation can be repeated, as many times as necessary, should it fail. Because inquiries can be repeated, error handling associated with the failure of the operation is simple. There is no need to install complex recovery logic during inquiries.

As this is an inquiry style application, and we do not need recoverability, we can use non-persistent messages both for the inquiry and the reply.

There may be two queues involved in this pattern. Since we do not need recoverability, for requests from the sender to the receiver, we can use a pre-defined queue. For the reply from the receiver to the sender, we can use a temporary queue.

Fire-and-Forget Update-Style Applications

This type of pattern can be used when an application requests changes to data at a server, but does not need to wait for an acknowledgement before proceeding. The figure below shows a client sending a request to a receiver that results in data being updated. There is no reply to acknowledge that the update is successful. By removing the need for immediate synchronous acknowledgement, we can reduce the total load on the server. This is a completely asynchronous, non-blocking, Point-to-Point design pattern:

click to expand

This design pattern has two important characteristics:

  • Firstly, it is entirely asynchronous. The client sender sends the request and immediately continues other processing. It assumes that the receiver server will process the request sometime in the future. The client sender does not receive any acknowledgement of its request.

  • Secondly, this is an update pattern. Data will be modified at the receiver server's end. It is therefore very important that the update is not lost. It may also be important not to repeat updates inadvertently.

Unlike inquiries, updates require some form of guaranteed message delivery. The level of guarantee totally depends on the cost associated with re-creation, should the update get lost.

Since some form of guaranteed message delivery is required, use a persistent message queue to hold the update request. Persistent messages are protected from loss even if the server crashes, or the network fails. This kind of message is delivered once, and only once, fulfilling the other criterion for this pattern.

There is only one queue involved in this pattern. You can use a predefined normal queue for the implementation.

Asynchronous Inquiry-Style Applications

This design pattern looks very similar to the pseudo-synchronous inquiry-style application pattern we saw previously. From a message queuing standpoint, many design decisions yield the same results as for the pseudo synchronous case. There is however, one major difference. The client sender does not wait for a reply to its request before continuing to process other things. For this pattern to be applicable the client should have something else to do after it has made the request, even though it may not have received any replies.

As the client sender does not wait for replies to its requests, some other mechanism needs to be employed to receive the replies as they come in. One solution might be to design a multi-threaded client, where one thread is dedicated to waiting for the results to arrive. The other solution is to use an event-based API if it's available.

There are therefore two approaches:

  • One involves starting a second thread of execution within the application. The thread waits for the arrival of messages. When a message arrives, the thread reads it, and stores the data it contains in the appropriate data structure.

  • The second approach requires that the chosen message queuing product's API can support asynchronous message receipt.

The figure below shows the asynchronous inquiry-style application design pattern:

click to expand

The Asynchronous Inquiry pattern has two important characteristics:

  • Firstly, it is asynchronous at the client. Once the request has been issued, the client goes on to do other processing without waiting for a reply.

  • Secondly, the pattern is an inquiry. Data at the server is not affected by running the application and the operation can be repeated as many times as necessary if it should fail. However, the main difference between this inquiry-style and the pseudo-synchronous style pattern is that we don't regard delayed replies as errors.

Since recoverability is not required, as with the pseudo-synchronous inquiry, we can use non-recoverable messages. This means we can use non-persistent messages.

When it comes to a decision on queues, there are a couple of queues involved in this pattern. For results flowing to the client, we can use a temporary dynamic queue. For requests flowing to the server, we can use a normal, pre-defined queue.

Pseudo-Synchronous Update-Style Applications

This is the most tightly coupled design pattern that we will look at. In many respects, it is also the least satisfactory of all the patterns that we will encounter here. Albeit, it is actually the pattern adopted by all client/server applications that do not use messaging, simply because alternative mechanisms offer little else. Every synchronous, blocking RPC call uses this pattern internally.

The next figure shows, this pattern. As with the synchronous inquiry pattern, the client cannot continue until it has received a reply from the server:

click to expand

There are two important characteristics of this pattern:

  • Firstly, it is synchronous. The client sender sends the update request but must wait for the acknowledgement message before proceeding.

  • Secondly, this is an update. Data will be modified at the server. It is important the data is not lost and that the update request is not repeated inadvertently.

The problem with the pattern is what to do if the client does not receive an acknowledgement. In the case of the inquiry operation, we could just stop waiting and ignore any reply that arrived subsequently. However, we can't do this when an update is being acknowledged. If an acknowledgement is delayed the client waiting for it has absolutely no idea whether or not the server executed the operation correctly. The client probably has to assume that the operation failed, remember the failure, and attempt to resolve the issue by communicating with the server at a later time. All this logic has to be added to the application. The solution to this kind of problem is to use distributed transaction processing and products like BEA Tuxedo or IBM CICS. These systems guarantee that updates occurring on the client and server are all part of the same unit of work that either occurs together or not at all. Using asynchronous update-style applications with acknowledgement design pattern is a better solution to this than using distributed transaction processing products since they tend to be more expensive to buy and operate than message queuing systems.

Since this is an update operation, you are required to use a persistent message delivery mechanism so that you get once and once only delivery of the request and the acknowledgement. Similarly, use a predefined normal queue to send messages. For acknowledgements, we need to use a permanent dynamic queue and probably control its deletion.

Asynchronous Update-Style Applications with Acknowledgement

In this pattern, the client sender is interested in the update process, but does not need to wait for it to complete before continuing. The figure below shows an asynchronous update-style application, with acknowledgement required:

click to expand

This pattern has a couple of important characteristics:

  • Firstly, it is entirely asynchronous. The client sender sends an update request and can immediately continue other processing.

  • Secondly, this is an update. Data will be modified at the server. It is important that the update is not lost and does not repeat inadvertently.

This pattern is very similar to the asynchronous inquiry pattern except for the fact that we connot lose the request or the acknowledgement. Therefore, we must use persistent messages. The requests and acknowledgements require some kind of message delivery guarantee. The level of guarantee really depends on the cost associated with re-creation, should the update get lost. Therefore, use perssent messages to hold both the updates and the acknowledgement.



Professional JMS
Professional JMS
ISBN: 1861004931
EAN: 2147483647
Year: 2000
Pages: 154

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