Observers Should Never Throw Exceptions

On Observers Throw Local Exceptions, William Grosso asked: How do we throw exceptions in an Observer?


The Observer shouldn't throw exceptions. There is no-one to catch them. The protocol could catch and ignore them, but that's dangerous. The Observable doesn't know anything about the Observers - that's the point of the pattern - so is not interested in their failure. -- Dave Harris

Agreed. In Cee Plus Plus terms, Observers should provide a Nofail Exception Guarantee. -- Tim Lesher


You need to use a two-phase protocol between the Observable and Observers. In phase one, the Observable proposes the change to the Observables; they can agree to the change or veto it. In the second phase, the Observable updates its state and informs the Observers of the change. This protocol is used in the Java Beans framework as "veto-able properties" and "bound properties".


William Grosso said, (with some paraphrasing): This is related to Observables Need To Be Consistent, because when an observer throws an exception, it flows right through the observable and we wind up with the same problem as on Observables Need To Be Consistent.

The question is: is this entirely theoretical? Have people actually enforced this stricture? Does it not bite us because exceptions rarely happen in an Observable context? And does the need to guarantee this constitute a huge limitation on exceptions?


In the Java world, this stricture is habitually enforced by default. That language requires exceptions to be declared by routines which throw them. When you design your Observer protocol, you naturally don't mention exceptions in it and so they cannot be thrown. For example, in the standard library we have:

interface java.util.Observer { public abstract void update( Observable o, Object arg ); }

Classes conforming to this interface cannot throw exceptions from the update() method. So it's not theoretical, it's standard practice.

(Actually, there are two groups of exception that don't need to be declared. They are for handling bugs and other catastrophic errors. I don't believe this weakens the case.) -- Dave Harris

Those two cases can break a lot of code if not handled properly. If you're implementing an event firing mechanism you should consider

catching Throwable whenever you hand an event to another object. Who knows what stupid things it will do, and one Null Pointer Exception can ruin your whole Thread.

Firing off a new Thread to do the handoff to the object. The object may do take an awful long time to respond, or get into a deadlock.

The AWT event thread seems to handle the first of these but not the second. Most naive implementations of event dispatchers don't handle either.


Leading us to the idiom Dont Throw Generic Exceptions. A reasonable stricture and one that I frequently observe in the breach. :-)


The way I see this is that the message from the Subject to Observer needs to be a "one way" message - it notifies the observer but doesn't return anything to the subject: no result or exceptions. Starting a new thread in java is one implementation of this. One way messages are useful for lots of things, see Doug Lea's Concurrent Programming In Java.

Two phase check & act protocols, like Java Beans and Smalltalk's changeRequest are a different and more difficult case.


The main issue is what happens when an Observer is coded incorrectly and throws a Runtime Exception. If the Observable is not coded defensively (i.e. does not catch (Runtime Exception rte) around each call to the observer's interface), its event delivery loop will halt (and perhaps the Runtime Exception propagates). This means that the other Observers do not get the event notifications. By following Observers Should Never Throw Exceptions, you assume the Observer is not coded defensively, as well as violating the Throw Dont Catch pattern.

I prefer to code the Observable defensively - you never know if your Observer obeys Observers Should Never Throw Exceptions or not. If you do this, it is not necessary to catch Runtime Exception in each Observer's/listener's method.

Perhaps we need a Collect Exceptions pattern, as a special case of Nested Exception, to collect the exceptions caught by all the observers.


Observers Should Never Throw Exceptions does not mix with Somebody Elses Framework (and neither does Checked Exceptions for that matter). More than once, I needed to build a new control based on an existing control. Sometimes I can do GUI event interception and translation, sometimes I cannot. However, there is often an observer for a property of the original control that in some manner reflects the event that needs to be translated. So, I derive from the base class, add an observer in the constructor (thus ensuring that I see it first), and mutate properties of the object at will.

If the change is not valid, I set it back to what it was. It would be nice to throw an exception sometimes to describe why (if some code causes that particular change and not a GUI event).




See original on c2.com