Vaadin Framework 8 renewed essentially the whole data binding API and added dozens of enhancements. Here is a list of the most important changes that will give you a boost in your next Vaadin Framework projects.

New modern Java APIs

The main feature in Vaadin 8 is core API modernization. We now fully take advantage of parameterization, lambdas etc. Upgrading to Vaadin 8 is still easy as legacy APIs are still available in a compatibility package.

Pass lists of entities directly to Grid and Selects

The most common way to populate Grid  and various select components has become much simpler and more typesafe. Just pass the list or array of your model objects directly to your Grid  or select component:

    List<Person> persons = Backend.getPersons();
    Grid<Person> grid = new Grid<>(Person.class);
    grid.setItems(persons);

ItemCaptionGenerator

ItemCaptionGenerator is a handy way to define a customized caption for options in selects:

    List<Person> persons = Backend.getPersons();
    ComboBox<Person> comboBox = new ComboBox<>();
    comboBox.setItemCaptionGenerator(p -> p.getFirstName() + " " + p.getLastName());
    comboBox.setItems(persons);

Type safe value change listeners

ValueChangeListeners are now parameterized with the field value type, which makes wiring the business logic easier:

    comboBox.addValueChangeListener(evt -> assert(evt.getValue().getId() == 42));

Grid column definition with type safe lambda expressions

A type safe mechanism to define columns that is faster to use in IDE and much easier to understand:

    Grid<Person> grid = new Grid<>();
    grid.setItems(persons);
    grid.addColumn(Person::getFirstName).setCaption("First Name");
    grid.addColumn(Person::getLastName).setCaption("Last Name");

Easier lazy loading of data from backend

Previously, for a memory efficient lazy loading solution you needed to implement a complex Container  interface. Now, in most cases, you can do a lazy binding to your backend using two lambda expressions:

    grid.setDataProvider(
        (sortorder, offset, limit) -> service.findAll(offset, limit),
        () -> service.count()
    );

Inline Converter with lambda expression

You can define a convertor inline using two lambda expressions:

    new Binder<Person>().forField(textField)
        .withConverter(
            textToInteger -> Integer.parseInt(textToInteger),
            integerToText -> integerToText.toString()
        )
        // or with method references:
        // withConverter(Integer::parseInt, Object::toString)
        .bind("age");

Validators can be defined both before and after conversion

You can define field validators both based on the value type of the field or the converted value that will be used in your business objects:

    new Binder<Person>().forField(tf)
        .withValidator(str -> str.length() == 4, "Must be 4 chars")
        .withConverter(new StringToIntegerConverter("Must be Integer"))
        .withValidator(integer -> integer.equals(2017), "Wrong date")
        .bind(Person::getBirthYear, Person::setBirthYear);

Legacy APIs still supported

For components with dramatic changes, we have preserved the legacy components in a compatibility package. With the migration tool you can upgrade to Vaadin 8 in a snap and start using new improved APIs gradually. Update the version of the Vaadin Maven Plugin to the latest available version and run:

    mvn vaadin:upgrade8

Support for HTML5 History API

History API makes it possible for single-page web apps to change the location of the browser and this way support proper deep linking, back button and search engines, without hashbang (“#!” in URL) haxies:

    // push state:
    Button button = new Button("Go to page 1");
    button.addClickListener(e -> {
        // URL will change to .../page1
        Page.getCurrent().pushState("page1");
    }); 

    // pop state: 
    Page.getCurrent().addPopStateListener(event -> {
        String uri = event.getUri();
        // ... update the UI accordingly
    });

HTML imports

HTML imports are a technology needed for utilizing Web Components. Since Vaadin 8, HTML imports are supported by the Framework, without need for special add-ons or low level JavaScript extensions:

    // bower install -save game-card
    // implement the server-side component:
    @JavaScript("GameCard.js")
    @HtmlImport("vaadin://bower_components/game-card/game-card.html")
    public class GameCard extends AbstractJavaScriptComponent {
        public GameCard(String symbol, String rank) {
            callFunction("setCard", symbol, rank);
        }
    }

    // implement the client-side component (GameCard.js):
    com_example_GameCard = function () {
        var element = this.getElement();
        this.setCard = function (symbol, rank) {
            element.set("symbol", symbol);
            element.set("rank", rank);
        };
    };
    com_example_GameCard.tag = "game-card";

Add components and automatically expand them

The new addComponentsAndExpand  method removes boilerplate code when adding components that need to be expanded:

    HorizontalLayout header = new HorizontalLayout(title, logout);
    VerticalLayout root = new VerticalLayout(header);
    root.addComponentsAndExpand(grid);

Helpful guidance in exception messages

Exceptions thrown by the framework often contain a verbose explanation in the error message about how to fix the code:

Image title

Improved defaults

Because Vaadin 8 is a major version, the team had a chance to modify the default settings of some commonly used components. Less to configure, more time to think about your actual UI.

Null values are displayed as empty strings by default

In earlier Vaadin versions, TextField  rendered null values as “null”, which may have been a good choice for developers, but useless for end users. Now the default is an empty string as it should be:

Image title

Ordered layouts now have better defaults

Vaadin UIs now look better than ever by default. Margin and spacing defaults have been adjusted in most commonly used layouts and you don’t need to call setMargin  and setSpacing  that often:

With Vaadin 7 With Vaadin 8
Image title Image title

Eager field validation

Vaadin 8 supports using proper validation while the user is typing in fields. This improves the UX to desktop level:

    User user = new User();
    TextField textField = new TextField("Vaadin 8");
    Binder<User> binder = new Binder<>();
    binder.setBean(user);
    binder.forField(textField)
        .withValidator(new StringLengthValidator("Too short", 8, 256))
        .bind(User::getUsername, User::setUsername);

Improved performance

The new data binding code is much easier and productive for developers, but it also saves quite a bit of memory and CPU.

Up to 10 times less overhead in in-memory listings

The new data access mechanism consumes multitudes less memory when listing in-memory data. Previously, the most commonly used Container BeanItemContainer , eagerly created a wrapper for each and every domain object you wanted to list. Now extra memory is not wasted for non-visible objects at all.

A fraction of previous CPU consumed when listing large datasets

When listing in memory data, bean introspection is no more done at all or done on demand. This saves a lot of CPU cycles, when listing a large number of rows in your data grids. In a simple test with 100 000 entities listed in a Grid , the server CPU time needed to serve the view was dropped from 233ms to 9ms.

Built for the future

There are some changes that might actually remove “features”, but which allow us to add exciting new features in upcoming minor releases.

Modern web browsers supported

By dropping legacy browser support, we can start using more modern web technologies, like CSS3 flexbox layouting, and add client side optimizations which were not possible before.

Java 8 or newer required

Using JDK 8 features in the API allows us to build features faster and in a more elegant way. Many of the API improvements presented above wouldn’t have been possible while supporting JDK 7.

Modern Java server required

Vaadin 8 requires Servlet 3 container, which also rules out some legacy servers. Less hacks needed for old servers which results into more maintainable code base.

New hook for add-ons to configure themselves

Vaadin add-ons can now hook to application initialization using VaadinServiceInitListener  interfaces, built on Java’s standard ServiceLoader mechanism. This can make the usage of certain Vaadin add-ons much easier:

    // file META-INF/services/com.vaadin.server.VaadinServiceInitListener:
    com.example.MyListener

    // file: MyListener.java:
    import com.vaadin.server.ServiceInitEvent;
    import com.vaadin.server.VaadinServiceInitListener;

    public class MyListener implements VaadinServiceInitListener {
        @Override
        public void serviceInit(ServiceInitEvent event) {
            // Configure service, add session init listeners,
            // request handlers etc...
            // ...
        }
    }

Are you ready to build your first Vaadin 8 app? Read the tutorial or visit the documentation site.

21 improvements in Vaadin 8

| Java Language| 1,399 views | 0 Comments
About The Author
- Developer Advocate at Vaadin Ltd

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>