Directory

← Back

Blackboard

A generic blackboard system for listening to and firing events.

Author

Rating

Popularity

<100

Sometimes, having a deep component hierarchy poses a problem, when you need to inform a component high up in the tree that something happened deep down below. You normally have one of two choices - either pass the listener all the way down the hierarchy, leading to more coupled code, or let each component in between be a listener/notifier, passing the event all the way back up.

With the Blackboard, you can register any listener to listen for any event, and when that event is fired, all the listeners for that event are triggered. This keeps your components clean and rid of unnecessary boilerplate code.

Versions 1.1.0 and 1.2.0 have a dependency to Google Collections.

Sample code

public class ExampleApplication {

  private static final Blackboard BLACKBOARD = new Blackboard();

  public static void main(final String[] args) {

    BLACKBOARD.enableLogging();

    /*
     * Informs Blackboard that all TestMessageEvents should be sent to all
     * objects that implement TestMessageListener.
     * 
     * Keeping all registrations in one central place will make the code easier
     * to read, and mitigates application bugs regarding late registration.
     */
    BLACKBOARD.register(TestMessageListener.class, TestMessageEvent.class);

    /*
     * Adds the two objects as listeners into Blackboard. Blackboard will now
     * inform these objects whenever an event is triggered that is registered to
     * their interface.
     * 
     * The MessageConsumer implements TestMessageListener, which listens to
     * TestMessageEvents. When the event is fired, the MessageConsumer prints
     * out the message in the event.
     * 
     * Note that order is not guaranteed by Blackboard. I.e. the order in which
     * the listeners are triggered is probably not the same in which the
     * listeners were added.
     */
    BLACKBOARD.addListener(new MessageConsumer(1));
    BLACKBOARD.addListener(new MessageConsumer(2));

    /*
     * These strings will be passed to the two MessageConsumers just added to
     * blackboard, without any apparent direct connection.
     * 
     * Each of these strings will appear twice in the console, since there are
     * two listeners interested in them.
     */
    sendString("Hello listeners");
    sendString("How are you doing?");
  }

  private static void sendString(final String message) {
    BLACKBOARD.fire(new TestMessageEvent(message));
  }
}



/**
 * A class that listens for {@link TestMessageEvent TestMessageEvents} and
 * echoes them out immediately.
 */
public class MessageConsumer implements TestMessageListener {

  private final int id;

  public MessageConsumer(final int id) {
    this.id = id;
  }

  /**
   * This method an example implementation of
   * {@link TestMessageListener#receiveTestMessage(TestMessageEvent)}, defined
   * by the listener interface.
   */
  public void receiveTestMessage(final TestMessageEvent event) {
    final String message = event.getMessage();

    System.out
        .println("[MSG] " + this + " got the message \"" + message + "\"");
  }

  @Override
  public String toString() {
    return getClass().getSimpleName() + id;
  }
}



/**
 * The event that is passed from {@link ExampleNotifier} to
 * {@link com.github.wolfie.blackboard.example.TestMessageEvent.TestMessageListener
 * TestMessageListener} .
 * <p/>
 * This class is simply a event wrapper for a string message.
 */
public class TestMessageEvent implements Event {

  /**
   * This interface represents a typical listener.
   * <p/>
   * The class name describes clearly what it is listening for and the method
   * name describes naturally what the listener is trying to do.
   */
  public interface TestMessageListener extends Listener {
    @ListenerMethod
    public void receiveTestMessage(final TestMessageEvent event);
  }

  private final String message;

  /**
   * Creates a new {@link TestMessageEvent} with a given message that will be
   * passed from notifier to listener.
   * 
   * @param message
   *          The message to pass
   */
  public TestMessageEvent(final String message) {
    this.message = message;
  }

  public String getMessage() {
    return message;
  }

  @Override
  public String toString() {
    return getClass().getSimpleName() + ": " + message;
  }
}

Compatibility

(Loading compatibility data...)

Was this helpful? Need more help?
Leave a comment or a question below. You can also join the chat on Discord or ask questions on StackOverflow.

Version

it is now allowed to register one listener to handle several events

Released
2012-04-27
Maturity
STABLE
License
Apache License 2.0

Compatibility

Framework
Browser
Browser Independent

Blackboard - Vaadin Add-on Directory

A generic blackboard system for listening to and firing events. Blackboard - Vaadin Add-on Directory
Sometimes, having a deep component hierarchy poses a problem, when you need to inform a component high up in the tree that something happened deep down below. You normally have one of two choices - either pass the listener all the way down the hierarchy, leading to more coupled code, or let each component in between be a listener/notifier, passing the event all the way back up. With the Blackboard, you can register any listener to listen for any event, and when that event is fired, all the listeners for that event are triggered. This keeps your components clean and rid of unnecessary boilerplate code. Versions 1.1.0 and 1.2.0 have a dependency to Google Collections.
Online