Thursday, November 13, 2008

Correlating Messages


Asynchronous messaging means that the sender doesn't receive an immediate reply or confirmation of receipt. After sending a message for processing by a remote service, most applications require at least confirmation that the message was received and acted upon, and often require the results of the remote process. Remember—in a normal application, even if a method doesn't return a value, the system at least knows that the method has had a chance to execute.

A reply message is a message received in response to another message. Reply messages are generally document or event messages, but are distinguished by being associated with a particular message. Typically, this association is accomplished by assigning each outgoing message a unique identifier (MOM systems do this automatically). If an incoming message is a reply, it includes a reference to the message the remote application is replying to.

JMS includes built-in functionality for associating a reply message with the original. Each JMS message, upon creation, is assigned a message ID, which is accessible via the JMSMessageID property of the Message class. Messages also have a JMSCorrelationID field, not set by default. When composing a reply message, it's standard practice to take the JMSMessageID and store it in the JMSCorrelationID field. Assuming that message and reply are valid JMS messages, and that reply is a response to message, this is how we'd set the correlation:

Command Message


Distributed applications can be a command and control nightmare. Multiple web applications expose different interfaces to the administrator, and actions that affect multiple systems need to be repeated. Tools like JMX (the Java Management Extensions) alleviate this problem to a degree, but only within controlled environments. It can be irritating, but the real challenge comes when disparate applications need to control each other. Since user interfaces are generally not designed to be used by other computers, some kind of remote command infrastructure is required.

A command message allows one system to control another application, or a series of other applications, by sending a specially formatted message to that system. A command message includes instructions to perform a specific action, either via headers and attributes, or as part of the message payload. The recipient performs the appropriate action when the message is received. Command messages are closely related to the Command pattern from GoF, which we discussed back in Chapter 3. They can be thought of, in fact, as a remote version of this pattern.

Security is a particular concern with command messages. MOM products provide a variety of mechanisms for securing a message channel. If these products are adequate for your needs (they often are), receipt of a command message can be treated much like an RPC call. If you're using a transport system that doesn't provide security guarantees, such as email, consider the security options we discussed for document messages.

Event Message


Event handling in Java should be familiar to you by now; but on the off chance that it isn't, here's the primer: an object can register itself with another object as an event listener. Once the listener has been registered, the target has a handle to the listener and can use callback methods to notify the listening object that a particular event has occurred. This process allows programmers to easily modify runtime behavior by plugging new listeners in at appropriate places. Swing is full of listeners, as is the Servlet API (ServletContextListener, etc.). The Gang of Four identified this behavior as Observer, in which the actor is the object or set of objects performing the main actions, and the observer is the listener.

An event message extends the Observer model to a set of distributed applications. The basic informational content of an event message is implicit in the fact that the message has been sent. Event messages can be sent from one system to another to provide notification of lifecycle events within an application, or to announce the status of particular activities. Applications for this pattern include enterprise monitoring (see the discussion of the control bus later in this chapter) and centralized logging.

An important characteristic of event messages is that they do not require a reply. In fact, one could go so far as to say there is no requirement that event messages be received, either. In some cases this is true, and in others it isn't: whether events must be received should influence your choice of message transport.

In JMS, an event message can be implemented with the user-defined headers of a message. The benefit of this approach is simplicity: applications only need to agree on header names, so there is no need to define a format for the message data. Performance improves, too, since JMS and most MOM packages provide built-in functionality to filter messages based on their headers.

Nonguaranteed messaging


Nonguaranteed messaging is like standard postal service. Your message will probably get there, but you don't know exactly when or in what condition. You also don't know if something goes wrong: there's no notification when your letter slips out of the bag and gets wedged in a corner of the Duluth post office.

Internet email, as defined by RFC 822, is the archetypical nonguaranteed messaging system. In fact, it's very consistent: messages sent to a valid address almost never get lost, and are delivered in a timely manner. In a controlled environment, receipt rates in the five-nines (99.999%) range aren't out of the question. Of course, delivery guarantees are only part of the issue. RFC 822 messaging provides no guarantee that a message will only be delivered and processed once, or that the message won't be changed in transport (corporate firewalls and virus detection packages frequently modify the format of a message). The application is responsible for verifying integrity and making sure that the order of processing is handled correctly. There are also no security guarantees; with SMTP, for instance, it is trivially easy to create a "spoof" message that appears to be from a particular source: receipt of a message provides no assurance that the message is genuine.

In return for a little extra work, you get the basic global infrastructure for free. Nonguaranteed messaging is often the only option when dealing with widely distributed sites, getting integrations up and running quickly with external partners, or when one actor in the messaging interaction is a human.

In J2EE, email integration is handled via the JavaMail API, which, out of the box, supports sending messages via SMTP and receiving them via POP3 or IMAP.[3] JavaMail is actually a generic messaging API, and additional plug-ins are available to support other messaging schemes, such as NNTP, the protocol behind Usenet.

Guaranteed messaging


Guaranteed messaging uses middleware to ensure that a message is properly delivered to its destination, both ungarbled and in a reasonably timely fashion. The middleware implementing the messaging framework guarantees a message sent to a valid destination eventually arrives, even if the destination is temporarily unreachable.

Guaranteed delivery doesn't imply complete certainty. Specifying a nonexistent destination won't get your message delivered, regardless of how expensive your middleware is. And if a destination system is unavailable for a long period of time, the middleware will probably return the message to its sender rather than wait indefinitely. What is guaranteed, however, is the contract between the messaging client and the server governing how a message will be handled. Undeliverable messages won't vanish into the night but will be handled according to a specific and well-known set of rules.

Message Oriented Middleware systems implement guaranteed messaging. Senders and recipients work through a MOM server, which is responsible for tracking all elements of the message lifecycle. MOM servers often provide a range of options for the message content itself: XML, Java objects, raw binary data, and so on. J2EE clients interact with MOM servers using JMS, the Java Message Service. JMS, which is part of J2EE 1.3, provides a standard programmatic interface to the different MOM implementations, much as JDBC does for database servers. Sonic Software's SonicMQ and IBM's MQSeries products are two of the leading MOM products

Interactions


A client calls a business method of the business delegate. The delegate locates the correct business service and connects to it. The business service grants the business delegate access to the relevant business objects. The business delegate manipulates the business objects and returns the result to the client.

Constant services locator

A typical ServiceLocator takes a JNDI directory name from the client and performs the requested lookup. This creates a coupling between all the various client calls to the locator and the directory structure—and when the directory structure changes, the client must be updated in many places. One variation of the ServiceLocator defines a constant set of services and lets clients access those services with a locator-specific name. This decouples the clients from the actual directory structure, allowing access to the new directory with only a single change to the locator.