All articles

Simplicity & Focus Through Server-Driven Web UI Development

Being a full-stack developer is a complex undertaking these days. As you might remember, it hasn't always been like this. There are multiple reasons for this evolution. One example is ever-growing responsibilities (think of DevSecOps). Another is specialised tooling for different aspects of the stack getting more and more complicated.

In particular, the UI aspects have increased in complexity over the years. There are various factors motivating it. One of the most important ones is the rise of single-page application frameworks (SPAs). A JavaScript frontend that uses API calls to display data or perform some action requires to build HTTP APIs for all UI-related interactions. For many types of back-office applications those APIs represent accidental complexity.

Jmix, being a full-stack business application framework, offers the server-side development approach with the help of Vaadin. Let's see how it works and why removing the dividing line between frontend and backend helps in a lot of scenarios.

What is server-driven web UI development with Jmix & Vaadin?

Server-driven web UI development generally means that the UI and the server side are closely working together to perform some business functionality. In this architecture, the UI and the backend of a business domain have a high cohesion as they provide a particular business feature together.

Let’s compare this to the SPA approach, where the frontend and the backend have a clear and strong dividing line through an explicit API. The coupling is much lower in this scenario as the two parts only communicate through an explicit contract.

Generally speaking, having low coupling is considered beneficial between independent components. But are the UI and backend actually independent from one another, or do they actually form a single logical component? If this is the case, having a high cohesion is actually desirable, as this is the nature of a single component.

In case of back-office UIs, the frontend and backend functionality are closely aligned. Therefore, the cost of introducing low coupling between the UI and the server side is very high. It brings no additional value but causes harm in terms of efficiency and unnecessary decoupling.

With the server-driven UI the frontend and backend code is often written in the same programming language.

For web applications, this has previously partly been possible for an application that used server-rendered HTML. In the Java world, solutions like JSP or Thymeleaf were using this approach to create the user interface with the help of Java. There are domain-specific languages / APIs, but the language was mostly the same. Still, developers had to learn the basics of the web with HTML & CSS.

With the rise of JavaScript and SPAs in particular, where more and more logic went to the web browser, using the same language was becoming less popular. Yet powerful frameworks emerged that make server-side driven web UIs possible, like Phoenix Liveview, Blazor for C#, or Vaadin in the Java ecosystem.

Conceptually they all follow the same principle: the application developer writes UI logic in their preferred backend languages like Elixir, C#, or Java. The framework performs some translation to make this available in the browser. This way, the developer does not have to think about the frontend and backend as separate components only due to technological restrictions.

How Vaadin works

Vaadin (Vaadin Flow to be more precise) is a set of web components and a Java API. An application developer writes the UI layout arrangement in Java. Vaadin uses this information to create the corresponding UI components in the browser.

When the user interacts with the components (like clicking a button), it creates a call-back to the server that triggers the corresponding Java method declared as an event listener.

The framework takes care of the interaction between the browser and the server, so no explicit API is needed to connect your UI to the backend.

It also keeps track of each user session and the state on the server to perform the corresponding dispatch of the method invocations.

In a strong frontend-backend separation the client code normally performs dedicated API calls via JavaScript to trigger an action on the server-side. As the majority of interactions reside on the client, very few manual API calls are performed. Vaadin, on the other side, transfers the majority of UI interactions to the server.

Let’s look at an interaction example. Jmix Petclinic example contains a calendar view for the visits for a particular month:

There are two buttons to change the month to display. When clicking the button, the following Java code is executed and the UI in the browser is refreshed with the visit data of the previous month:

@UiController("petclinic_Visit.browse")
@Route(value = "visits")
public class VisitBrowse extends StandardLookup<Visit> {
    //...
    @Subscribe("navigatorPrevious")
    protected void onNavigatorPreviousClick(Button.ClickEvent event) {
        calendarNavigators
                .forMode(
                        CalendarScreenAdjustment.of(calendar, calendarNavigator, calendarTitle),
                        datatypeFormatter,
                        calendarMode.getValue()
                )
                .navigate(PREVIOUS, calendarNavigator.getValue());
        loadEvents();
    }
}

The interaction performed by Vaadin is the following:

The JavaScript part of Vaadin (Vaadin Client) handles the button click on the browser and delegates the request to the backend part of the Vaadin component (Vaadin Server). This will lookup the context and the current user session. Afterwards Vaadin dispatches the click event to the Java UI code on the server-side.

The UI code will update the calendar component and refresh the data. This happens by interacting through the Vaadin Java API to update some Vaadin components. The Vaadin Server component will pick up the components to update and transfer the new component state to the Vaadin Client in the browser. This will mirror the requested updates in the browser so that the user can finally see the previous month data.

What Jmix adds to the table

Jmix is a Rapid Application Development framework for building data-centric business applications. One of its cornerstones is Vaadin as a UI rendering engine. Jmix enables declarative creation of the UI layout in XML, which is less verbose than programmatic building of UI in Java, as is done with pure Vaadin. The XML layout can be edited manually or in the visual designer. Jmix Studio is a tool based on IntelliJ IDEA. It provides the described functionality.

Jmix also provides features specifically targeted at enterprise applications, such as large collections of data-aware UI components extending the Vaadin library. One example is a sophisticated filter component allowing end users to construct arbitrary filtering conditions.

Besides, it comes with a set of modules providing optional features: from data access control and audit to reporting and business process management. Many Jmix modules include a user interface, which seamlessly integrates into the resulting full-stack application. And this inherited UI can be easily customised in the application, thanks to Vaadin's server-side programming model and extendable Jmix UI layouts written in XML.

Benefits of server-driven UI development

This approach has a couple of advantages compared to the frontend-backend separation, but it is also only beneficial under particular circumstances.

Reduced complexity

First of all, it removes cognitive load, as the overall solution is simpler from a developer's point of view. No need to think about two ecosystems to program in lets the developer focus more on the value-add of the application you want to produce. Java developers can leverage their existing knowledge for topics like debugging, dependency management, static code analysis tooling, testing approaches, etc.

Abstraction, on the other hand, is always a double-edged sword. It is good as long as there is no need to look under the covers. Therefore, in some scenarios, it is absolutely crucial to have access to the JavaScript ecosystem in its entirety. This is not so easy when using Vaadin compared to a dedicated JavaScript SPA in place.

One additional technical benefit is that there is little code duplication. In Jmix / Vaadin you use the same domain models for your business logic as for your UI. Removing duplication significantly drives down complexity. Validation logic is kept in one place and does not have to be mirrored in the UI code and the backend API code.

Security

From a security point of view, Vaadin’s architecture also has some benefits. It never exposes its internals to the browser and instead only sends to the web browser the exact data that is required to update the UI. This is an inherently more secure development approach compared to the situation where it is up to the developers to transfer the right data for a particular UI interaction. This can lead to too much data exposed to JavaScript by API endpoints.

Full-stack teams

When working in cross-functional teams with a strict frontend-backend separation, it often leads to the situation that the team itself divides on this line, as the different areas need dedicated expertise. Here the architecture drives the sub-team boundaries as commonly known by Conway's Law. In this case, it is an unfortunate development that leads to developers having a harder time thinking about the whole end-to-end business process as they are only responsible for one part.

Full-stack developers can clearly see the implications of modelling something in the data model and what problems/benefits it might bring to the UI parts. Vaadin promotes this model implicitly, as it reduces the entry barrier for backend developers to do frontend-related work.

This also brings another interesting benefit to the table. When having small teams, Single Language Development enables them to still bring the whole application to life. It does not require dedicated frontend developers in the teams.

On the other hand, for a lot of frontend developers, this approach of developing the UI with backend technologies is quite uncommon. Therefore, based on the existing team structure, it can either be a benefit or a drawback.

Limits of Vaadin’s UI approach

The architectural Vaadin approach is not a silver bullet. The fact that every UI session is represented on the server puts a certain memory burden on the backend. This is fine for most business applications, where the number of concurrent users is tens of thousands, not millions. But an application with tens of millions of concurrent users working with UI would require a tremendous amount of memory.

When it comes to Jmix and the focus on business applications, this limitation is not a real problem. But there are applications that have a public customer-facing part in addition to the back office where this huge number of concurrent users could come from. In this case, a hybrid approach with a REST API for the particular use-cases of the public frontend combined with an additional SPA mitigates this limitation.

Jmix is an open-source platform for building enterprise applications in Java