Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

21 Improvements in Vaadin 8

DZone's Guide to

21 Improvements in Vaadin 8

Vaadin 8 was a major overhaul, deprecating some old features to introduce new support for JDK 8, modern Java APIs, improved type safety, and easier backend lazy loading.

· Java Zone
Free Resource

Navigate the Maze of the End-User Experience and pick up this APM Essential guide, brought to you in partnership with CA Technologies

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);

Typesafe 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 Typesafe Lambda Expressions

A typesafe 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 the 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 Expressions

You can define a converter 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 the 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 the Previous CPU Consumed When Listing Large Datasets

When listing in-memory data, bean introspection is no longer 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 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 layout, 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 a Servlet 3 container, which also rules out some legacy servers. Less hacks needed for old servers, which results in a 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.

Thrive in the application economy with an APM model that is strategic. Be E.P.I.C. with CA APM.  Brought to you in partnership with CA Technologies.

Topics:
java ,vaadin ,typesafe ,lazy loading

Published at DZone with permission of Alejandro Duarte. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

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

{{ parent.tldr }}

{{ parent.urlSource.name }}