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>
- Set Vaadin version along with other properties
- Keep the version of all dependencies consistent
- 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 } }
- Associates the component to the Vaadin servlet subcontext root
- Set the static page title. In case you need a dynamic title, you can implement HasDynamicTitle
- Define a
RootComponent
class VerticalLayout
is a class that Vaadin renders as an HTMLdiv
- The Vaadin Spring Boot starter takes care of injecting the list
- Vaadin executes the
init()
function at the first browser request - 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.
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!"))
- 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!")
label()
is a Karibu DSL extension function on theHasComponent
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 }
- Initialize a new
Checkbox
component with a value - 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