Another way to decouple your server components

Submitted on 05 May 2012

One of Vaadin strongest points is the way you can reuse components from project to project inside JARs. This can only be achieved if these components are nicely decoupled from one another.

In Learning Vaadin, I showed how to decouple them using DI. However, this way only handles “static” coupling - the way a component depends on another to be displayed, it doesn’t handle “dynamic coupling”, the way a component depends on another to do something. For example, a list box values could depend on the selected value of another list box.

In order to achieve this kind of behavior, it would be nice if components could send and receive events.

Vaadin doesn’t provide this feature out-of-the-box but there are many frameworks that tackle events management: CDI (aka JSR 299), Google’s Guava EventBus and so many more.

In this article, I chose Guava for the following reasons: it doesn’t depend on a platform, it’s usable with Java 5 and it only draws a single dependency, making it nearly self-contained. As the use-case, let’s have two combo boxes, one for countries, the other for capitals. When the country changes, the capital has to be selected.

It’s of first importance that the combos do not know about each other, so let’s bury them underneath a hierarchy of components.

public class FirstComponent extends CustomComponent {
 
    private ComboBox cb = new ComboBox("Country");
}

Guava event management is based entirely on the EventBus class. Some steps are necessary:

  • Listener methods should be annotated with Guava’s @Subscribe
  • Listener method should declare as their only parameter the type of event they’re interested in handling:
@Subscribe
public void changeCapitalOnCountryChange(CountryChangedEvent event) {
 
    ...
}

Note there’s no enforcement on the event type’s hierarchy, you can basically pass whatever strikes your fancy (provided it’s not a simple type).

  • The bus registers listener instances.
 
bus.register(new SecondComponent());
  • Producers have to post new events into the bus. In our case, this has to be done when a ValueChangeEvent is received (from the client-side):
public void valueChange(ValueChangeEvent vcEvent) {
 
    bus.post(new CountryChangedEvent());
}

Basically the only coupling you’ll ever have is between the producer and the event bus.

In order to reduce the previous coupling, let’s design the producer’s constructor to take the bus as a parameter, so as to be able to inject it:

public class FirstComponent extends CustomComponent {
 
    public FirstComponent(final EventBus bus) {
 
        ...
    }
}

The complete source code is available on GitHub.