The first time I encountered the whiteboard (or blackboard) pattern was when reading the pragmatic programmer. Since then I have seen it a few times. The major mainstream use of the whiteboard I have seen is in Dependency Injection frameworks like Google Guice and Spring.
In my opinion these DI frameworks might better be described as an implementation of the whiteboard pattern for service (dependency) location and contribution, which also do dependency injection. They can provide you objects from the whiteboard – one way they do that is by DI. But they also can do it in other ways, the Guice Injector can be used as a factory directly (using the getInstance method). Or by providing factory implementations (Providers or my favourite AssistedInject) that draw objects from the whiteboard.
In particular, this is very helpful when an application is structured for testability in a ports and adapters architecture. I am aware that Nat Pryce has an issue with DI frameworks not distinguishing between internals and peers, but I don’t think I have really run into that problem practically. I think probably he is also making the point that DI libraries can hide important information about how you objects are put together. I think both issues probably depend on how you use the DI library and which objects you choose to put into its whiteboard – in general avoid hiding the rules about relationships between your domain objects in your DI usage. BTW; I don’t think EventCast hides relationships in general (actually the opposite), but I can see how it could be used to do that.
So, onto the main point of this post.
The OSGi framework uses the whiteboard pattern to manage dependencies between bundles. In particular when one bundle is driven by events from another (supporting IoC). There is a provocatively named paper called Listeners Considered Harmful: The “Whiteboard” pattern on how they used the whiteboard pattern to replace the listener pattern.
I have recently been working on a library called EventCast based on my experiences using Guava EventBus. What it does is use Guice to implement the whiteboard pattern for OSGi style inter-object communication using interfaces to define the listeners (kind of a very light, stripped down, version of some of what you get with OSGi).
EventCast tries to be as unintrusive to the application code as it can. A single instance of the listener interface is injected into (hopefully the constructor(!) of) each object that wants to produce those events. Registering and unregistered of listeners (listener lifecycle), the threading model of the listeners and any listener error handling is managed separately from the producer. So your consumer just implements the interface it wants messages for, and your producer just calls methods on the injected instance of the listener interface. EventCast handles distributing the message to all of the currently registered listeners.
It is tightly integrated with Guice. It uses the Guice Whiteboard to store the EventCast listener implementation and make it available to the rest of the application. It detects additions of new listeners to the Guice Whiteboard and registers them for any produced events.