/ Vaadin

Binding Groovy beans to Vaadin Fields

Say we have the following simple Person POJO from our application model and we want to tie the first name and last name fields to Vaadin Labels.

public class Person {

    String firstName;
        
    String lastName;        
}

This is very common scenario when making CRUD applications where you want to display the first and last name of a person.

In Vaadin and Java what we usually do is wrap the original POJO in a BeanItem and pass that BeanItem's property as the data source to the TextField. Like so:

Person person = new Person()

BeanItem item = new BeanItem<Person>(person)

Label lastNameLabel = new Label(item.getItemProperty("lastName"))

When the property of the BeanItem changes then the BeanItem notifies the Label that the first or last name has changed and the label updates the value on the screen.

We need to use the BeanItem wrapper around the original POJO since Java doesn't provide us with a way to listen for changes. While it works, it has the downside that when we change the original value in the POJO itself, nothing happens. This is because the BeanItem is unaware of changes to the underlaying POJO if we don't use the BeanItem API to update with. So we always have to update the BeanItem instead of the POJO which commonly leads to our application passing around BeanItems instead of the actual POJO in the APIs.

However, this is not the case if we use some Groovy magic. Lets take a look how we would do the same thing in Groovy, but without a wrapper.

Groovy provides us with the @Bindable annotation which we can use directly on the POGO. Here is the same Person POGO in Groovy.

class Person {

    @Bindable String firstName

    @Bindable String lastName
}

The only difference is the @Bindable annotation on the fields which will let us listen to changes on those fields we apply the annotation on.

Now, lets bind the last name property again to a Vaadin Label but this time use Groovy:

// Create a person
def person = new Person()

// Create a label for persons last name
def lastNameLabel = new Label()

// Bind the last name to the field
person.propertyChange = {
    if(it.propertyName == 'lastName'){
        lastName.value = it.newValue
    }
}

Now, if you go change the persons last name in the original Person POGO then the field value will automatically change in the Vaadin Label as well. This relieves us from maintaining any wrappers and lets us work directly on the POGO's instead without needing to worry about updating the UI specifically.