Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Follow the Chain of Responsibility

Run through server-side and client-side CoR implementations

  • Print
  • Feedback

Page 2 of 4

  • You want to decouple a request's sender and receiver
  • Multiple objects, determined at runtime, are candidates to handle a request
  • You don't want to specify handlers explicitly in your code


If you use the CoR pattern, remember:

  • Only one object in the chain handles a request
  • Some requests might not get handled


Those restrictions, of course, are for a classic CoR implementation. In practice, those rules are bent; for example, servlet filters are a CoR implementation that allows multiple filters to process an HTTP request.

Figure 2 shows a CoR pattern class diagram.

Figure 2. Chain of Responsibility class diagram

Typically, request handlers are extensions of a base class that maintains a reference to the next handler in the chain, known as the successor. The base class might implement handleRequest() like this:

   public abstract class HandlerBase {
         ...
         public void handleRequest(SomeRequestObject sro) {
            if(successor != null)
                  successor.handleRequest(sro);
         }
   }


So by default, handlers pass the request to the next handler in the chain. A concrete extension of HandlerBase might look like this:

   public class SpamFilter extends HandlerBase {
      public void handleRequest(SomeRequestObject mailMessage) {
         if(isSpam(mailMessage))   { // If the message is spam
            // take spam-related action. Do not forward message.
         }
         else { // Message is not spam.
            super.handleRequest(mailMessage); // Pass message to next filter in the chain.
         }
      }
   }


The SpamFilter handles the request (presumably receipt of new email) if the message is spam, and therefore, the request goes no further; otherwise, trustworthy messages are passed to the next handler, presumably another email filter looking to weed them out. Eventually, the last filter in the chain might store the message after it passes muster by moving through several filters.

Note the hypothetical email filters discussed above are mutually exclusive: Ultimately, only one filter handles a request. You might opt to turn that inside out by letting multiple filters handle a single request, which is a better analogy to Unix pipes. Either way, the underlying engine is the CoR pattern.

In this article, I discuss two Chain of Responsibility pattern implementations: servlet filters, a popular CoR implementation that allows multiple filters to handle a request, and the original Abstract Window Toolkit (AWT) event model, an unpopular classic CoR implementation that was ultimately deprecated.

Servlet filters

In the Java 2 Platform, Enterprise Edition (J2EE)'s early days, some servlet containers provided a handy feature known as servlet chaining, whereby one could essentially apply a list of filters to a servlet. Servlet filters are popular because they're useful for security, compression, logging, and more. And, of course, you can compose a chain of filters to do some or all of those things depending on runtime conditions.

With the advent of the Java Servlet Specification version 2.3, filters became standard components. Unlike classic CoR, servlet filters allow multiple objects (filters) in a chain to handle a request.

  • Print
  • Feedback

Resources