Friends of OpenJDK Today

Vaadin: Battery-Included Server-Side AJAX Framework

October 22, 2024

Author(s)

  • Avatar photo
    Nicolas Frankel

    Nicolas is a developer advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). ... Learn more

I've written a lot about Vaadin. I was so enthusiastic that I wrote the first book about it (besides the Book of Vaadin), its updated edition for Vaadin 7, and a companion website. Still, I'm amazed that so many people in the JVM world never heard of it.

In this article, I'd like to introduce Vaadin in the context of AJAX and SSR.

Short introduction to Vaadin

The beauty of Vaadin lies in its simplicity - you only write backend code. You read that well. A Vaadin developer only needs to know Java, or any JVM language, and the Vaadin API. At runtime, Vaadin will create the client-side code, i.e., HTML, JavaScript and CSS. This approach empowers developers to focus on the application's core functionality, making the development process more productive.

Vaadin builds upon components and layouts, just like regular desktop-based frameworks do. If you know Swing or JavaFX, you will feel right at home.

I mentioned CSS above: Vaadin allows you to develop your CSS in a dedicated reusable package called a theme. The icing on the cake: developing a theme can be done in parallel to backend development and has no adherence to the latter; the code doesn't need to use a specific template or to add specific classes to the HTML.

Vaadin setup

Setting up Vaadin in the context of Spring Boot is a breeze:

<project>
    <properties>
        <java.version>17</java.version>
        <kotlin.version>1.9.24</kotlin.version>
        <vaadin.version>24.4.9</vaadin.version>                   <!--1-->
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>               <!--2-->
                <version>${vaadin.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-spring-boot-starter</artifactId>   <!--3-->
        </dependency>
</project>
  1. Set Vaadin version along with other properties
  2. Keep the version of all dependencies consistent
  3. Add the Vaadin Spring Boot integration library

Vaadin builds upon a regular Java Servlet, which maps to the root by default. The Vaadin Spring Boot integration allows overriding the default. Because our codebase integrates multiple frameworks, we map it to /vaadin via the relevant property:

vaadin.url-mapping=/vaadin/*

At the first request from a client, Vaadin will return the JavaScript engine's code. The engine will make subsequent requests to retrieve the configured UI and scaffold the latter client side. From then on, the engine handles all user interactions and updates the UI if necessary.

First steps with Vaadin

Once we set up the project, we must configure which component Vaadin displays when it receives a request.

@Route("/")                                                       //1
@PageTitle("Vaadin")                                              //2
class TodoView(todos: ArrayList<Todo>) : VerticalLayout() {       //3-4-5

    init {                                                        //6
        // ...                                                    //7
    }
}
  1. Associates the component to the Vaadin servlet subcontext root
  2. Set the static page title. In case you need a dynamic title, you can implement HasDynamicTitle
  3. Define a RootComponent class
  4. VerticalLayout is a class that Vaadin renders as an HTML div
  5. The Vaadin Spring Boot starter takes care of injecting the list
  6. Vaadin executes the init() function at the first browser request
  7. The next code snippets will go there

Adding components

In the above snippet, we inherited from VerticalLayout, a Vaadin-provided component.

The Vaadin Design System includes a set of components that you can use to build your UI. The components have a server-side Java API in addition to the TypeScript API for client-side development.

You use a component by first creating it and then adding it to a containing layout.

-- Creating UI in Vaadin Applications

Some components can contain others, and they know how to lay their subcomponents out. For example, VerticalLayout places components top-to-bottom in a column; HorizontalLayout places them left-to-right in a row.

Adding components to a layout is straightforward:

add(Label("Hello"))                                               //1
add(Label("world!"))
  1. In the context of the init() function

While this works perfectly, we can improve the situation using Karibu-DSL since we use Kotlin. We can rewrite the above snippet as follows:

label("Hello")                                                    //1
label("world!")
  1. label() is a Karibu DSL extension function on the HasComponent interface

Karibu is great, but with a slight downside: it doesn't offer extension functions for the whole API. For example, you need to fall back to the regular API to add footer to a Grid component:

appendFooterRow().apply {
    getCell(completedProp).component = Button("Clean up") {
        todos.removeIf { it.completed }
        refresh()
    }
}

On the plus side, Karibu is Open Source, and you can always contribute if you have something to add.

Specific components related to the UI are not important for the general understanding. If you're interested, you can always check the source code.

User interactions

When mainframes were the kings of computing, you accessed them via terminals. The UI was pretty limited, and rendering occurred on the "dumb" terminal. Personal computers moved the rendering functionality from the server to the client. At this time, developers attached behaviour to a component via a trigger. For example, you could bind printing Hello world! when the user clicks a button.

Web applications changed this paradigm. As our previous articles showed, every interaction maps now to a request-response flow, synchronous or asynchronous. Vaadin brings us back to the original paradigm.

Checkbox(todo.completed).apply {                                  //1
    addValueChangeListener { todo.completed = it.value }          //2
}
  1. Initialize a new Checkbox component with a value
  2. When the value of the checkbox changes, execute the lambda - we change the underlying model's value

There's no need for JavaScript code; Vaadin manages the interaction independently.

Conclusion

The post was but a short introduction to Vaadin in the context of AJAX and SSR.

Most developers who learn programming on web apps and are thus used to the request-response model react poorly when exposed to Vaadin. Their main argument is the absence of API. IMHO, it's a benefit: some apps, particularly business apps, don't evolve to the point where you'll need to develop dedicated mobile clients.

Vaadin comes with a default CSS set, as stated in the introduction. This default theme ensures Vaadin applications look good from the start, providing users with a comfortable and visually appealing work environment. However, you can always integrate another or even develop your own.

The real benefit, however, is found again at the organizational level. In the introductory post, I mentioned that separating frontend and backend development creates issues during their integration. Because Vaadin does not have such a separation, project planning is more predictable, as there is no integration step between the front end and back end. Likewise, theming can happen in parallel to development.

The complete source code for this post can be found on GitHub.

To go further:


Originally published at A Java Geek on October 13th, 2024

Topics:

Related Articles

View All

Author(s)

  • Avatar photo
    Nicolas Frankel

    Nicolas is a developer advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). ... Learn more

Comments (0)

Your email address will not be published. Required fields are marked *

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Save my name, email, and website in this browser for the next time I comment.

Subscribe to foojay updates:

https://foojay.io/feed/
Copied to the clipboard