Over a million developers have joined DZone.

The Right Usage of lambdas with Event Listeners

· Java Zone

Discover how AppDynamics steps in to upgrade your performance game and prevent your enterprise from these top 10 Java performance problems, brought to you in partnership with AppDynamics.

There's been much advertisement about how Java 8's lambdas bring a big asset to Vaadin development. The following is a pre-Java 8 usage of a ClickListener:

button.addClickListener(new Button.ClickListener() {

    @Override
    public void buttonClick(Button.ClickEvent event) {

        container.addComponent(new Label("Button clicked"));
    }
});
Java 8's lambda make it much easier, as this snippet shows:
button.addClickListener(e -> container.addComponent(new Label("Button clicked")));
However, it is my opinion, that using lambdas this way leads to bad architecture and unmaintainable design, for it strongly couples GUI components and behavior.

Object-oriented design should follow SOLID principles, first among them being the Single Responsibility Principle:

In object-oriented programming, the single responsibility principle states that every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.

Using lambdas as in the previous snippet just defeats this principle. Enforcing it requires a dedicated class for the behavior:

public class ShowLabelListener implements Button.ClickListener {

    private final Container container;
    
    public ShowLabelListener(Container container) {
    
        this.container = container;
    }

    @Override
    public void buttonClick(Button.ClickEvent event) {

        container.addComponent(new Label("Button clicked"));
    }
}

Not only is this snippet sound Object-Oriented design, it allows to pass parameters to the constructor and store them as attributes. Usage of this listener would be as the following:

button.addClickListener(new ShowLabelListener(container));

Storing the container as an attribute in the listener is better than using lambdas directly, but introduces strong coupling from the behavior to the GUI in the form of an association. In this regard, I've already introduced Guava's EventBus in a former post.

This would translate into the following code:

public class ButtonClickedEvent {

    private ComponentContainer container;

    public ButtonClickedEvent(ComponentContainer container) {

        this.container = container;
    }

    public ComponentContainer getContainer() {

        return container;
    }
}

public class ShowClickMeListener {

    @Subscribe
    public void onClick(ButtonClickedEvent event) {

        event.getContainer().addComponent(new Label("Button clicked"));
    }
}

Usage then becomes:

button.addClickListener(new Button.ClickListener() {

    @Override
    public void buttonClick(Button.ClickEvent event) {

        bus.post(new ButtonClickedEvent(container));
    }
});

eventBus.register(new ShowClickMeListener());

Of course, this is a little verbose, and that's when lambdas come in here handy. The previous snippet can be updated with Java 8's lambdas as:

button.addClickListener(e -> bus.post(new ButtonClickedEvent(container)));

eventBus.register(new ShowClickMeListener());

IMHO, this is the right usage of lambdas in regard to Vaadin event listeners.

 

The Java Zone is brought to you in partnership with AppDynamics. AppDynamics helps you gain the fundamentals behind application performance, and implement best practices so you can proactively analyze and act on performance problems as they arise, and more specifically with your Java applications. Start a Free Trial.

Topics:

Published at DZone with permission of Nicolas Frankel , DZone MVB .

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}