WARNINGThis tutorial is still being written. Its content is already useful, but some parts are missing.
Introduction
This tutorial demonstrates how to develop applications in Vaadin Flow and Hilla: you can read and work through both, or focus on the one you prefer based on your needs and background. Since it’s written for newcomers to Vaadin Flow and Hilla, it might be worthwhile to go through both.
For those who choose only the Flow part of this tutorial, it’s assumed that the reader has some Java experience, if not necessarily experience with developing Java web applications. Along those lines, it’s also assumed that the reader has a basic understanding of how to develop applications using the Spring Boot open-source Java framework. This includes understanding Spring beans, dependency injection, the application context and scopes.
For understanding and getting the most from the Hilla part of this tutorial, in addition to the skills and experience expected for understanding the Flow section, the reader should also have basic skills in React, the open-source front-end JavaScript library for building user interfaces.
Learning Tasks & Concepts
In this tutorial, which is spread over several pages here, you’ll build a simple application and deploy it. The same application will be developed in both Flow and Hilla. For each, it’ll be a chat application, using the same backend — demonstrating the similarities and differences. The results will look and behave the same, but will be implemented differently, from a different development prospective.
The finished application will look like what you see in this screenshot:
Prerequisites
This tutorial uses Java 21. Vaadin works with Java 17, but to be able to use the latest features of the latest Java LTS (long term support) release, you’ll use version 21.
As for tools, you’ll use a web browser, Maven, and a Java IDE of your choice (e.g., IntelliJ, VS Code).
Key Concepts
Several concepts key for Vaadin will be explored and higlighted in this tutorial: views, routing, layout, server push, backend integration, and security.
View
A view is an application’s user interface page, or rather a composite of text, images, interactive components, and other elements the user may view and with which the user may interact. It typically fills up an entire browser tab, or a big portion of it.
Routing
This is the mapping of views to different URL paths. Navigating to a different view inside an application changes the URL path — which can contain path parameters.
Layout
A web application often has elements that are visible regardless of which view is currently active, such as an application header and a navigation menu. These elements are added to a layout. A layout also controls where the view is rendered inside it.
Server Push
In a web application, the browser sends a request to the server and the server responds. Server push is a mechanism in which the server can push data to the browser without first getting a request.
Security
Measures taken to protect the application from unauthorized use, including authentication and authorization of users.
Project Setup
In this tutorial, you can choose to implement the user interface of the chat application using either Java and Flow, or TypeScript, React and Hilla. In traditional web applications, you often see the concepts, frontend and backend. Frontend code runs in the browser; backend code runs on the server. The frontend is often synonymous with the user interface, whereas the backend is everything else: business logic, application services, REST APIs, etc.
In a Vaadin application, things are a little different. Flow allows you to write user interfaces using Java only. That means a big part of your user interface is actually running on the server — the backend. There’s also a frontend runtime, but you don’t have to touch it unless you want.
Hilla follows the more traditional approach in which the user interface runs solely in the browser. The following graphic illustrates this differece:
In a Vaadin application, it may be clearer to think in terms of presentation layer and application layer, rather than frontend and backend. These terms are conceptual layers that define where a piece of code belongs conceptually rather than physically. They also don’t have anything to do with layered architectures.
In a Flow application, the presentation layer has parts that run in the browser and parts that run on the server. In a Hilla application, the presentation layer runs only in the browser. The application layer is the same for both. It’s possible to combine Hilla and Flow in the same application. This is called a hybrid application, but it’s outside the scope of this tutorial.
Download the Starter
In this tutorial, the focus is on the presentation layer, only. Therefore, a starter project with a complete application layer has been created for you. It’s a Maven-project compressed as a zip-file that you can download from GitHub.
In order to understand the structure of this project, in the following section you’ll have a quick look at the underlying architecture of the application.
Architecture
Software architecture can be diagrammed in many different ways. A simple and intuitive way is the C4 model.
C4 takes its inspiration from digital maps with multiple levels. The highest level has the least amount of details. Zooming in on a level takes you to the next level that reveals more details, etc. The name C4 represents four levels: Context, Container, Component, and Code.
The highest level, the context shows how the software system fits into its surroundings. If you zoom in on the system, you get to the second level, which shows the containers that make up the system.
A container is an application or a data store. If you zoom in on a container, you get to the third level, which shows the components that make up the container.
A component is a grouping of related functionality encapsulated behind a well-defined interface. If you zoom in on a component, you get to the fourth and last level, which shows the code that implements the component.
The C4 model doesn’t require you to use all four levels. The application you are going to build during this tutorial is quite simple. You can jump straight to the container diagram, which looks like this:
The application consists of two containers: the user’s web browser; and a Spring Boot web application. Regardless of whether you build the user interface with Hilla or Flow, the containers remain the same. However, if you zoom in on them, you’ll see the components are slightly different. The web application container looks like this:
The application layer consists of two system components: Chat; and In-memory Storage. The chat component exposes an Application Programming Interface (API) for the user interface to call, and a Service Provider Interface (SPI) for storing and retrieving messages. This makes it possible to plug in different storage mechanisms without changing the chat component itself. In this tutorial, all chat messages are stored in memory. However, you could easily plug in another component that instead stores the messages in, for example, a relational database. This way of splitting systems into smaller components with clearly defined interfaces (i.e., APIs and SPIs) is a good praxis when building Vaadin applications and can be applied to both the application layer and the presentation layer.
If you implement the user interface with Hilla and React, Vaadin generates a TypeScript client that you can use to call the Chat API directly from the browser. You don’t need to worry about REST controllers; Vaadin takes care of that, automatically.
If you implement the user interface with Flow, you need to build a new system component, the Flow UI. This is a component that uses the Chat API directly inside the Java Virtual Machine (JVM). It doesn’t expose a public API for other components to use. Instead, Vaadin takes care of the rendering of the user interface in the browser, and the communication between the browser and the server.
A word of caution: When you build user interfaces, you construct them from components (e.g., buttons, text fields, grids, etc.). You can also have containers in your user interface, such as layouts containing other components. Especially when using both types of components and containers in the same setting, it may be a good idea to use prefixes to avoid confusion: UI containers and components related to the user interface, and system containers and components for the software architecture.
Project Structure
With the architecture in mind, take another look at the project structure in your IDE:
The chat component resides in the com.example.application.chat
package. Its API consists of all of the public classes and public methods in this package. One of them is ChatService
, which is a class you will be interacting with the most from the user interface. The spi
subpackage contains interfaces, and any classes needed by them, that a service provider component should implement.
The in-memory storage component resides in the com.example.application.inmemorystorage
package. Since it has no public API, all of its classes are package-private.
Finally, there is a Spring Boot application class, com.example.application.Application
. This class sets up the Spring application context, which wires the components together.
You would typically find the rest of the files in a Spring Boot application built with Maven.