All Articles ↓
8 months ago

Vaadin 10+ as the Future of CUBA UI

Since the very beginning, Vaadin was a cornerstone and a crucial part of the CUBA Platform UI. Thanks to its innovative approach, it helped CUBA to bring enterprise UI development to a very promising (and default nowadays) WEB land. One of the most exciting parts of Vaadin is that the whole development is isomorphic and being done primarily using Java, rescuing the developers from interacting with a fairly unstable and quickly changing front-end world.

Vaadin 8 project structure

As you may see, one of the important parts of Vaadin is a feature-rich UI (based on GWT widgets in case of Vaadin 8).

Compared with modern web UI kits even nowadays Vaadin widgets still belong to the most sophisticated and advanced ones, especially in terms of enterprise requirements. Primarily, we are talking about such heavily used in typical CUBA applications components as Tables, Grids, ComboBoxes. For example, just try to find a popular UI kit with a Table which provides drag-n-drop column reordering or dynamic column control.

Our Story with Vaadin

CUBA Platform has a long story of using Vaadin. The platform provides to its users almost seamless migration from Vaadin 5 to Vaadin 8. To provide such kind of migration we had to build and keep our API on top of Vaadin. Also, we extend some components and even fork the framework itself to provide unique functionality for our customers and inject required extension points. On the server-side the platform provides data binding and data-aware components which are the most important features of the Generic UI.

To speed up the development and to enable using rapid development tools (Studio) we introduced XML descriptors - declarative approach to build data-bound UI:

    <layout>
        <grid spacing="true" height="200">
            <columns count="4"/>
            <rows>
                <row flex="1">
                    <label value="Field 1" align="MIDDLE_LEFT"/>
                    <textField height="100%"/>
                    <label value="Field 2" align="MIDDLE_LEFT"/>
                    <textField height="100%"/>
                </row>
                <row flex="2">
                    <label value="Field 3" align="MIDDLE_LEFT"/>
                    <textField height="100%"/>
                </row>
            </rows>
        </grid>
    </layout>

Pure Vaadin:

    GridLayout tableHeader = new GridLayout(3, 2);
    
    Label nameLabel = new Label("Field 1");
    nameLabel.setWidth(lastnameWidth + 2 * 6, Unit.PIXELS);
    tableHeader.addComponent(nameLabel, 0, 0, 0, 1);
    Label countryLabel = new Label("Field 2");
    countryLabel.setWidth(countryWidth + 2 * 6, Unit.PIXELS);
    tableHeader.addComponent(new Label("Field 3"), 1, 0);
    Label bornLabel = new Label("Field 4");
    bornLabel.setWidth(bornWidth + 2 * 6, Unit.PIXELS);
    tableHeader.addComponent(bornLabel, 2, 0, 2, 1);
    tableHeader.addComponent(countryFilterBox, 1, 1);
    
    // Put the header and table inside a vertical layout
    layout.addComponent(tableHeader);
    layout.addComponent(table);
    
    // Adjust the table height a bit
    table.setPageLength(table.size());

We managed to build a list of our own components (based on Vaadin primitives):

  • GroupTable
  • Form (formerly FieldGroup)
  • PickerField
  • LookupPickerField
  • TokenList
  • MaskedField
  • SuggestionField
  • CurrencyField

That being said, CUBA provides quite a lot on top of the Vaadin Framework to make the developers' life easier and bring the development to a higher level. CUBA team did a heavy-lifting to enable very smooth, literally invisible migration when updating the underlying Vaadin Framework.

New Challenges

Customization and Native Interaction

GWT is quite complex, and creating UI widgets is a challenging and time-consuming process. Experienced developers know for sure that there is a high price you have to pay when you work with artificial abstractions over the native platform. In the case of GWT, we have to interact with browser JS APIs from the Java world.

Responsive Layouts

The ability to be adjustable for different screen sizes has become a crucial requirement even for enterprise interfaces. Making responsive UI is hard just because of the aforementioned additional abstractness over the native platform. Though you can use CssLayout or special add-on to create responsive UI, standard layouts and calculations on the server side do not play well for such purposes.

Using Third-Party Libraries

Web evolves very fast, there is an enormous amount of web packages (npm >1M) which are mostly useless in Vaadin 8 apps as it does not use modern front-end tooling and build systems.

GWT Development is Stuck

At some point, Google stopped active development of GWT. It’s not only about official support but more about the ecosystem.

Vaadin Flow

To be more open to the front-end ecosystem, Vaadin started to develop the successor of the Vaadin Framework. The core of the new approach is Vaadin Flow - technology that provides a server-side model and basic data binding for a new UI layer based on Web Components instead of GWT widgets.

Consider the following diagram:

Vaadin 10 based project

As you may see, Vaadin has replaced its GWT-based client-side with the new one based on native web technologies.

Vaadin Components

New Vaadin components are successors of Vaadin GWT widgets. They are Web Components built from scratch using pure web technologies (HTML, JavaScript) and Polymer 2 library.

Web Components

Initially, Web Components were a set of standards implemented in most modern browsers:

  • Custom Elements
  • Shadow Dom
  • HTML Templates
  • HTML Imports -> ES Modules

For a long time, Web Components were very promising, and many people (including me) considered them as a native replacement for frameworks like React and Angular which also utilize component-based approach. But with time it became obvious that some of these standards were dropped by browsers, and some require serious improvements. Nowadays, from the list above only Custom Elements and Shadow DOM are still used in web application development. HTML Imports was dropped even from Chrome. HTML Templates nowadays look already outdated and, for example, new Polymer approach: lit-html use them only behind the scenes.

We also had an experience with Web Components as part of our attempt to build a client-side centric UI on top of Polymer library. At some point, we decided to shift our efforts to the React-based approach since Polymer, despite its brave mission of Web Component enablement solution, had poor developer experience, small ecosystem (even after several years of existence), and finally made an unclear release of Polymer 3 which at the moment of releasing was not recommended for a new projects solution. Polymer users had to wait for almost a year until lit-html and LitElement were finally released.

Another observation coming from our experience: despite being heavily promoted by advocates of use the Platform motto, it’s still barely possible to escape transpilation/bundling step when developing modern front-end applications. While standards were making a hard way to be adopted by all browsers and settle APIs, the community created a lot of tools and libs to solve the same problems.

For example, the main purpose of Shadow DOM is to encapsulate CSS styles from being spilled to/from local DOM of the component. The idea is great, but it took several years to be adopted by most browsers (thankfully Edge moved to Chromium). At the same time, the React ecosystem was fulfilled by a huge amount of styling libraries that solve the same task and even more without significant pitfalls of Shadow DOM.

Nevertheless, Web Components have a very important distinctive feature: they are part of the Platform (browsers). Being not tied with any particular framework, in theory, they are universal and can be used everywhere. From that perspective, it looks like a reasonable choice for UI Kits or standalone components (but not for applications), made not only by Vaadin but, for example, also by Ionic and SAP.

Vaadin 14

Vaadin 10 based on Vaadin Flow has been released in the middle of 2018. It quickly became obvious that the UI kit misses a lot of important components and contains only basic ones. Moreover, the client-side build pipeline included a bower dependency manager - a tool that was already deprecated in 2017 and does not intersect with the de-facto standard npm ecosystem.

So we considered Vaadin 10 release as experimental and decided to wait until the new technology becomes more stable. There were 3 major releases until Vaadin 14 LTS arrived in August of 2019 with highly demanded npm support and more robust UI kit. That urges us to take a closer look and make some hands-on experience with Vaadin 14.

UI Kit

Even without deep dive into the codebase, it was clear that many properties and behaviors changed in comparison to Vaadin 8 widgets. Generally, it’s not bad but for CUBA it means that in some aspects there will be no direct replacements of the currently supported features/APIs.

In terms of completeness there are still some missing core components that are already used in CUBA:

  • Calendar
  • Tree
  • TwinColumn

Some of the previously free components and features become part of Pro Components: for example, RichTextArea now is part of Pro components, edit mode of Grid is available in Vaadin Grid Pro.

PickerField

As part of our evaluation process we reimplemented CUBA’s PickerField component for Vaadin 14:

text

Speaking of the server-side, Vaadin Flow provides amazing capabilities to interact with the client-side (DOM elements, events, etc) using Java APIs. Vaadin components are shipped with a convenient Java API:

    Accordion accordion = new Accordion();
    ...
    accordion.open(1);

Non-Vaadin components have no such APIs, but you can still use generic methods over DOM API for any element:

Example 1

    if (value == null) {
        getElement().removeProperty("value");
    } else {
        getElement().setProperty("value", getStringRepresentation(value));
    }

Example 2

    getElement().appendChild(new Element[]{Element.createText(text)});

While the server-side was pretty slick and clear, the client-side took almost 90% of our efforts. The first notable thing we should mention is that core Vaadin components are currently built with Polymer 2. To support Polymer 3 for Vaadin 14+ they are seemingly auto-converted. Generally, Polymer 2 and Polymer 3 have the same API (that’s why auto-conversion is possible), however, there are subtle differences in imports and styles declarations.

Another hard topic is styling and customization: thanks to Shadow DOM you simply cannot apply styling to random elements (only to those which are designed to be styleable by using custom CSS properties). Vaadin components have slots (another powerful, yet intricate part of Shadow DOM) for customization. They are great for simple use cases but you quickly face limitations when trying to implement more advanced use-cases.

So when implementing PickerField we end up by copy-pasting styles and other parts of Vaadin components and build the component on top of the native input element (the only reusable things imported from @vaadin were a couple of Mixins).

We don’t blame Vaadin as it has not been designed (and not ought to be) as a foundation for another UI kit, it just indicates that for us it will be a huge amount of work on the client-side to support all additions we provide for a long time for our developers. The Work which currently should be based on Polymer 3 (already in maintenance mode) with all known developer experience flaws of Polymer2.

Latest news

Just at the time of writing this article, Vaadin announced that all core components will be rewritten on TypeScript and LitElement. We look positively at this decision since our vast experience with TypeScript confirms that it helps to avoid lots of bugs caused by the absence of static typing in JS, helps to understand the structure of codebase, to perform safe refactorings, etc.

LitElement/lit-html looks a little more doubtful though: we understand the choice because it’s a successor of Polymer, and utilizes powerful declarative rendering ( view=f(state) ) approach invented by React. But it’s still:

  • Very new.
  • Has a runtime (unlike compiled approaches like Stencil and Svetle). To support both Polymer and Lit- based components Vaadin should ship both libraries to the client-side.
  • Poor IDE support. There are a few of VS Code plugins, but no support in IntelliJ/WebStorm, which makes lit-templates look really messy.
  • Not SSR - friendly.

Many new questions arise:
Will LitElement + TypeScript supersede current Polymer 3 based approach to develop application front-end?
If yes - how such React-like rendering will work altogether with server-side Java API?

Update

Vaadin 15 is coming with client-side bootstrapping and TypeScript support.

Conclusion

Vaadin is a unique product that enables convenient web development for Java. Vaadin Flow brought a completely new client-side approach which we think is quite promising. However, the component set is still evolving and on its way to stability.

One thing we can say for sure: as a consequence of the completely new client-side we'll be unable to provide a smooth migration path to the new UI built on top of Vaadin Flow.

Also, we feel it’s still a little bit fuzzy and unstable in terms of client-side technologies to start a massive migration of all CUBA components on top of it. We decided to postpone the active development until the new set of web components becomes available. We still keep an eye on the Vaadin development and ready to re-evaluate it as soon as it becomes more stable.

At the same time, we are also trying to provide an alternative, client-side friendly approach to create UI: see our recent blogpost on TypeScript SDK and React Client.

Vlad Minaev