Home > Java, Uncategorized > EventBus: Introduction and troubleshooting for annotation problems

EventBus: Introduction and troubleshooting for annotation problems


Today I ran into a problem with a great project I use called EventBus, so I figured I’d use it as an opportunity to introduce the project, as well as give a solution to the problem I was facing.

EventBus, an open-source Java project, is described on its homepage as

Pub-sub Event broadcasting mechanism, Swing-oriented

In a nutshell, the publication/subscription mechanism is an alternative to explicitly defining listeners and adding them to objects of interest (the Observer/Observable pattern). This is beneficial because it allows for a more modular, late-binding approach to events. As the EventBus page describes,

“It replaces the tight coupling introduced by explicit listeners with a flexible loosely coupled design. ”

Here is the typical MVC type code for having objects notified of changes in state (from my post about creating a solar system model in Java):

public class SolarSystemModel extends Observable {

    // snip

    public void setDay(int day) {
        int oldDay = this.day;
        this.day = clampDay(day);
        if (oldDay != this.day) {
            setChanged();
            notifyObservers();
        }
    }

    public void setHour(int hour) {
        int oldHour = this.hour;
        this.hour = clampHour(hour);
        if (oldHour != this.hour) {
            setChanged();
            notifyObservers();
        }
    }
}
public class  SolarSystemView extends JComponent implements Observer {

    public void update(Observable o, Object arg) {
            repaint();
    }

}

This works fine but note a couple problems.
1) I am forced to either make my domain object extend Observable, in which case I lose out ability to subclass other more useful classes, or forced to roll my own Observer type interfaces, hold a list of listeners, add them all manually.

2) If we were to add another class that visualized the solar system, it would need to get a handle to the solar system model and be tightly coupled with it.

EventBus strives to get away from explicit listeners that the model objects need to keep track of. Instead, there are feeds of objects or topics that interested classes can register their interest in and receive the updated objects. The above example could be redone using EventBus as follows:

public class SolarSystemModel {

    // snip

    public void setDay(int day) {
        int oldDay = this.day;
        this.day = clampDay(day);
        if (oldDay != this.day) {
            EventBus.publish(this);
        }
    }

    public void setHour(int hour) {
        int oldHour = this.hour;
        this.hour = clampHour(hour);
        if (oldHour != this.hour) {
            EventBus.publish(this);
        }
    }
}

public class  SolarSystemView extends JComponent implements EventSubscriber<SolarSystemModel> {

    public SolarSystemView() {
        // Snip
        EventBus.subscribe(SolarSystemModel.class, this);
    }

    public void onEvent(SolarSystemModel m) {
        // Use the updated solar system model to repaint
        repaint();
    }
}

Again, note that the model now is free to extend whatever class it wants, rather than Observable.

This example is a bit too trivial to fully illustrate the power of EventBus; for a more real world example see the excellent article on refactoring a Swing financial app to use EventBus.

In addition to explicitly declaring that you are an EventSubscriber, you can annotate methods in your object to announce the same intent. For instance, rather than doing something like

public class View implements EventSubscriber<ModelClassA>, EventSubscriber<ModelClassB>, EventSubscriber<ModelClassC> {

    public View() {
        EventBus.subscribe(ModelClassA.class, this);
        EventBus.subscribe(ModelClassB.class, this);
        EventBus.subscribe(ModelClassC.class, this);
    }

    public void onEvent(ModelClassA) {
        // Handle this type of object
    }

    public void onEvent(ModelClassB) {
        // Handle this type of object
    }

    public void onEvent(ModelClassC) {
        // Handle this type of object
    }
}

you can instead name the methods however you want, using annotations:

public class View {

    public View() {
        // Important: without this line, the annotations will not be read
        AnnotationProcessor.process(this);
    }

    @EventSubscriber(eventClass=ModelClassA.class)
    public void handleTypeA(ModelClassA) {
        // Handle this type of object
    }

    @EventSubscriber(eventClass=ModelClassB.class)
    public void handleTypeB(ModelClassB) {
        // Handle this type of object
    }

    @EventSubscriber(eventClass=ModelClassC.class)
    public void handleTypeC(ModelClassC) {
        // Handle this type of object
    }
}

This is a good feature, since it allows you to customize the naming of your methods, providing more descriptive names than “onEvent”.

OK, after that rather lengthy introduction, here is the problem I was running into:

“incompatible types
required: java.lang.annotation.Annotation
found: org.bushe.swing.event.EventTopicSubscriber”

It was fairly inscrutable to me, so once I found out what was going on, I figured I had to write about it.

The problem is that there are identically named classes, one for the actually implementation, and one for the annotation. So instead of importing

org.bushe.swing.event.EventTopicSubscriber

you must instead import

org.bushe.swing.event.Annotation.EventSubscriber

If you use the “Fix all imports” in NetBeans, it will automatically choose the wrong one.

  1. Stuart Blair
    May 31, 2010 at 12:56 am

    Great post. That would have driven me crazy. Any chance you could link to the article you referred to on the refactoring of a Swing financial app to use EventBus?

    Thanks
    Stuart

  2. Jason
    July 12, 2010 at 1:13 pm

    thank you!

  3. September 10, 2014 at 2:27 am

    I will right away grab your rss as I can’t in finding your e-mail subscription link or e-newsletter service.
    Do you have any? Kindly allow me understand so that I could subscribe.
    Thanks.

  1. February 23, 2011 at 11:30 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: