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

The Chain of Responsibility pattern's pitfalls and improvements

Don't call the next chain node in your concrete chain class anymore

  • Print
  • Feedback

Recently I wrote two Java programs (for Microsoft Windows OS) that must catch global keyboard events generated by other applications concurrently running on the same desktop. Microsoft provides a way to do that by registering the programs as a global keyboard hook listener. Coding did not take long, but debugging did. The two programs seemed to work fine when tested separately, but failed when tested together. Further tests revealed that when the two programs ran together, the program that launched first was always unable to catch the global key events, but the application launched later worked just fine.

I resolved the mystery after reading the Microsoft documentation. The code that registers the program itself as a hook listener was missing the CallNextHookEx() call required by the hook framework. The documentation reads that each hook listener is added to a hook chain in the order of startup; the last listener started will be on the top. Events are sent to the first listener in the chain. To allow all listeners to receive events, each listener must make the CallNextHookEx() call to relay the events to the listener next to it. If any listener forgets to do so, the subsequent listeners will not get the events; as a result, their designed functions will not work. That was the exact reason why my second program worked but the first didn't!

The mystery was solved, but I was unhappy with the hook framework. First, it requires me to "remember" to insert the CallNextHookEx() method call into my code. Second, my program could disable other programs and vise versa. Why does that happen? Because Microsoft implemented the global hook framework following exactly the classic Chain of Responsibility (CoR) pattern defined by the Gang of Four (GoF).

In this article, I discuss the loophole of the CoR implementation suggested by GoF and propose a solution to it. That may help you avoid the same problem when you create your own CoR framework.

Classic CoR

The classic CoR pattern defined by GoF in Design Patterns:

"Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it."


Figure 1 illustrates the class diagram.

Figure 1. CoR class diagram

A typical object structure might look like Figure 2.

Figure 2. CoR object structure

From the above illustrations, we can summarize that:

  • Multiple handlers may be able to handle a request
  • Only one handler actually handles the request
  • The requester knows only a reference to one handler
  • The requester doesn't know how many handlers are able to handle its request
  • The requester doesn't know which handler handled its request
  • The requester doesn't have any control over the handlers
  • The handlers could be specified dynamically
  • Changing the handlers list will not affect the requester's code


The code segments below demonstrate the difference between requester code that uses CoR and requester code that doesn't.

  • Print
  • Feedback

Resources