Blog

Vaadin Framework 8 comes with Java 8 native APIs

By  
Matti Tahvonen
Matti Tahvonen
·
On Sep 19, 2016 7:01:00 AM
·

For a web framework whose history spans back 15 years, Vaadin Framework contains an insane number of modern web technologies. It has been an SPA (single-page application) before the term was coined, it uses WebSockets for a constantly open communication channel, Sass for enhanced theme building and you can easily wrap a WebComponent based JS widgets with a clean Java API for use in Vaadin applications.

We have been really active taking in all the new stuff that has become possible regarding web as an application platform, but we have been rather conservative in taking full advantage of JVM and Java, which has also developed with leaps. In Vaadin 8, we focus the core of the product, the Java API that you use to build your awesome UIs, and make that faster and easier to use.

Most of the API in Vaadin is still valid and perfectly functional. You can even use e.g. lambdas with certain features, but it has been designed in an era with no generics, lambda expressions, method references and even without a proper java.util.collections package.

Getting rid of millstones around our neck

Oracle has dropped their support for Java 7 and IBM has a modern Java 8 support, so nobody on Earth should be using Java 7 or 6. But we know there still are people who are using them. To make big leaps forward we need to let something go. Vaadin 7 will still be supported for the minority of Java developers who are still bound to old Java versions, for one reason or another.

Also, we will be dropping support for some old browsers, most notably IE 8-10. If Microsoft thinks nobody should use them, so should you. We know this is rough for some users, but we just need to go forward. This will make us much more agile to develop our components in upcoming versions.

Backwards compatibility, in terms of API compatibility, is another thing that might make you a bit afraid of the upgrade as well. We won’t promise a 100% backwards compatibility as we want to clean some old methods from our components, but we’re making a special backwards compatibility module which will make upgrading to Vaadin 8 much simpler than the previous Vaadin 6 to Vaadin 7 upgrade.

Data binding renewed - less and simpler code

Most of the renewals in Vaadin 8 will be related to “data binding”: how to connect data to tabular components, how to populate options in select components and how to bind business objects to field components in forms.

Previously Vaadin developers used a lot of proprietary interfaces called Containers, Items and Properties to do the databinding. In the early days of JVM this was a good idea, but in the modern era of Java, most Vaadin developers just wrap their lists of beans using a helper class called BeanItemContainer, and give that container to e.g. Vaadin ComboBox component. In Vaadin 8, we just pass the beans directly to the component.

Also, with previous versions, if there was some customization needed for the presentation, either a custom DTO or tricky work with the Container-Item-Property stuff was needed. Now, you can often change the presentation with a single lambda expression.

The following common use case, implemented with both Vaadin 7 and a pre-release of Vaadin 8 emphasises how dramatic a difference the “containerless” modern API can make:

Before:

ComboBox comboBox = new ComboBox();
List<Contact> contacts = service.findAll();
BeanItemContainer<Contact> beanItemContainer = new BeanItemContainer<>(Contact.class);
GeneratedPropertyContainer gpc = new GeneratedPropertyContainer(beanItemContainer);
gpc.addGeneratedProperty("name_combined", new PropertyValueGenerator() {
   @Override
   public Object getValue(Item item, Object itemId, Object propertyId) {
       String firstName = (String) item.getItemProperty("firstName").getValue();
       String lastName = (String) item.getItemProperty("lastName").getValue();
       return firstName + " " + lastName;
   }

   @Override
   public Class getType() {
       return String.class;
   }

   @Override
   public Container.Filter modifyFilter(final Container.Filter filter) throws UnsupportedFilterException {
       final SimpleStringFilter ssf = (SimpleStringFilter) filter;
 
       return new Container.Filter() {
           @Override
           public boolean passesFilter(Object itemId, Item item) throws UnsupportedOperationException {
               final It/nem generatedItem = gpc.getItem(itemId);
               String fullname = generatedItem.getItemProperty("name_combined").getValue().toString();
               // Ignore case as ComboBox
               return fullname.toLowerCase().startsWith(ssf.getFilterString());
           }
 
           @Override
           public boolean appliesToProperty(Object propertyId) {
               return "name_combined".equals(propertyId);
           }
       };
   }
 
});
comboBox.setContainerDataSource(gpc);
comboBox.setItemCaptionPropertyId("name_combined");

After:

ComboBox<Contact> comboBox = new ComboBox<>();
comboBox.setItems(service.findAll());
comboBox.setItemCaptionProvider(c-> c.getFirstName() + " " + c.getLastName());

Simpler, faster and more readable, that is the code you write with Vaadin 8.

When building forms, in the future you’ll use a concept called BeanBinder, which directly accepts your domain objects. The BeanBinder also contains a lot of cool improvements regarding form validation and makes it much easier to create top notch UX for your end users. The new BeanBinder also gives you much more control to customize how your form works, like where and how to present validation errors. The validation can be executed dynamically, as the user is still typing in, and enabling the primary action only when it can actually be executed. The BeanBinder has full support for cross field validation using JSR 303 validators and you can define your validation rules as a single lambda expression.

The code example below shows how to bind a phone number and email TextField to a Contact bean, with slightly different methods and custom validators.

final Contact contact = new Contact();
 
final TextField phone = new TextField();
final TextField email = new TextField();
Button save = new Button("Save");
 
final Predicate<String> requirePhoneOrEmail = v -> !phone.getValue()
       .trim().isEmpty() || !email.getValue().trim().isEmpty();
 
final BeanBinder<Contact> binder = new BeanBinder<>(Contact.class);
binder.forField(email)
       // cross field validation, both programmatic Vaadin specific
       // style and JSR 303 validators are supported
       .withValidator(requirePhoneOrEmail,
               "Both phone and email cannot be empty")
       // express simple validators using on line lambda expressions
       .withValidator(value -> value.length() > 3,
               "Email must be longer than 3 letters.")
       // or use some of the built in validators, like before
       .withValidator(new EmailValidator("Incorrect email address"))
       // bind to email property in Contact bean
       .bind("email");
 
binder.forField(phone)
       .withValidator(requirePhoneOrEmail,
               "Both phone and email cannot be empty")
       // bind with explicitly set getter and setter lambdas
       .bind(Contact::getPhone, Contact::setPhone);
 
// Trigger cross-field validation when the other field is changed,
// not needed with JSR 303
email.addValueChangeListener(event -> binder.validate());
phone.addValueChangeListener(event -> binder.validate());
 
binder.setStatusHandler(new BinderStatusHandler() {
   @Override
   public void accept(BinderValidationStatus<?> t) {
       // react to validity changes
       save.setEnabled(t.isOk());
   }
});

This is just the tip of the iceberg. There are many other exciting enhancements coming up. For example, a super easy way of connecting lazy loading components to data without a need to build a custom Container. We believe that Vaadin Framework 8 will make your life as a Java developer much easier.

Developer preview released at JavaOne

We have been working a lot on these changes and we are confident that we are on the right track. But at the same time, we also know we have been looking at these changes from a short distance - probably missing some important details about our API. Thus, we want your help! Even though a lot of things are still in flux, you can try out the next generation of Vaadin API today with 8.0.0.alpha2 and help us make web development easier than ever.

As usual, quite a few people from our team are at JavaOne. Come meet with some of the core developers who can answer even the trickiest questions related to the new versions. Visit our booth and the Vaadin Meetup at JavaOne to give us new ideas and get more insights of Vaadin 8!

See the in progress documentation for data model in version 8

 
Matti Tahvonen
Matti Tahvonen
Matti Tahvonen has a long history in Vaadin R&D: developing the core framework from the dark ages of pure JS client side to the GWT era and creating number of official and unofficial Vaadin add-ons. His current responsibility is to keep you up to date with latest and greatest Vaadin related technologies. You can follow him on Twitter – @MattiTahvonen
Other posts by Matti Tahvonen