Server-Side Web UI Frameworks

This section documents Spring Boot 4.1.x and Spring Framework 7.0.x on the Java 17/21+ baseline, as described by the official Spring Boot reference documentation and each sub-project’s own site (Spring Data, Spring for Apache Kafka, Micrometer, Project Reactor, springdoc-openapi, Spring gRPC, and the others listed in this section’s Bibliography) — which are the references these pages are written and verified against.

This content was generated with the assistance of AI and should be verified against those official docs before being relied on in production. Spring Boot and its ecosystem continue to evolve; the examples here target the current 4.1.x / 7.0.x releases.

This section’s bibliography lists the reference material consulted while preparing these pages.

A Spring Boot application that renders its own HTML has three broad options: classic server-rendered templates, a richer component-based UI framework, or a plain REST API paired with a separate front end. This page compares Thymeleaf, Vaadin, and legacy JSF (via JoinFaces) and closes with a decision table.

Thymeleaf

Thymeleaf is a natural templating engine: its templates are valid HTML that can be opened directly in a browser or by designers, with th:\* attributes added as extra markup rather than special tags or non-HTML syntax. spring-boot-starter-thymeleaf auto-configures an ITemplateResolver (and the SpringTemplateEngine/ThymeleafViewResolver that use it) that resolves view names returned from Spring MVC controllers to .html files under src/main/resources/templates.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
@Controller
public class GreetingController {

    @GetMapping("/greeting")
    public String greeting(@RequestParam(defaultValue = "World") String name, Model model) {
        model.addAttribute("name", name);
        return "greeting"; // resolves to templates/greeting.html
    }
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
    <p th:text="'Hello, ' + ${name} + '!'">Hello, placeholder!</p>
</body>
</html>

The th:text attribute replaces the element’s placeholder body when the template is rendered by the engine, but the placeholder text keeps the file valid, browsable HTML on its own.

Fragments and layouts

th:insert and th:replace pull a reusable fragment (e.g. a page header or footer) into a template, so common markup lives in one file:

<!-- templates/fragments/layout.html -->
<footer th:fragment="footer">
    <p>&copy; 2026 Example Corp</p>
</footer>
<!-- templates/page.html -->
<div th:replace="~{fragments/layout :: footer}"></div>

th:insert keeps the including tag and nests the fragment inside it; th:replace substitutes the fragment in place of the including tag entirely.

Form binding

th:object binds a form to a command/backing bean, and th:field binds each input to one of its properties — generating the matching id, name, and value attributes and wiring up validation error display:

@Controller
public class RegistrationController {

    @GetMapping("/register")
    public String form(Model model) {
        model.addAttribute("registration", new RegistrationForm());
        return "register";
    }

    @PostMapping("/register")
    public String submit(@Valid @ModelAttribute("registration") RegistrationForm form,
                          BindingResult result) {
        if (result.hasErrors()) {
            return "register";
        }
        // persist form...
        return "redirect:/register/success";
    }
}
<form th:action="@{/register}" th:object="${registration}" method="post">
    <input type="text" th:field="*{email}" />
    <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email error</span>
    <button type="submit">Register</button>
</form>

See Thymeleaf in the Spring Framework reference for the Spring MVC integration and the Thymeleaf documentation for the full th:\* attribute reference.

Vaadin: a component-based alternative

Where Thymeleaf renders discrete HTML pages per request, Vaadin builds a rich, stateful UI out of server-side Java components (grids, forms, dialogs) that push DOM updates to the browser over a persistent connection — closer to a desktop-style UI toolkit than to page templating. Reach for Vaadin when the application needs complex, interactive views (data grids with inline editing, multi-step wizards, real-time updates) built entirely in Java; reach for Thymeleaf when pages are simpler, mostly read-and-submit, and benefit from designer-friendly, natural HTML templates.

This page does not duplicate Vaadin’s own documentation. See the Vaadin Reference section for the framework itself, and its Spring Boot Integration page for how a Vaadin UI is wired into a Spring Boot application.

JSF via JoinFaces (legacy)

JSF is documented here for completeness and for maintaining existing legacy systems. It is not a recommended choice for new Spring Boot projects — prefer Thymeleaf, Vaadin, or a separate single-page front end (React/Angular/Vue) talking to a REST API.

JoinFaces integrates JSF into Spring Boot’s auto-configuration model, which Spring Boot does not support out of the box. Adding a JoinFaces starter auto-configures a JSF implementation (Mojarra or MyFaces) as an embedded FacesServlet, plus, when its starter is present, a component library such as PrimeFaces:

<dependency>
    <groupId>org.joinfaces</groupId>
    <artifactId>jsf-spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.joinfaces</groupId>
    <artifactId>primefaces-spring-boot-starter</artifactId>
</dependency>

With those starters on the classpath, .xhtml views under src/main/resources/META-INF/resources (or src/main/webapp) are served without any manual web.xml or faces-config.xml setup — JoinFaces registers the FacesServlet and wires JSF managed beans into the Spring ApplicationContext automatically. See the JoinFaces reference documentation for supported JSF implementations, component libraries, and configuration properties.

Choosing an approach

Approach Best for Notes

Thymeleaf

Simple, mostly server-rendered pages; SEO-friendly public sites; designer-editable HTML

Auto-configured by spring-boot-starter-thymeleaf; stateless per-request rendering

Vaadin

Rich, stateful, data-heavy UIs built entirely in Java (dashboards, back-office apps)

See Vaadin Reference; higher server-side session cost

REST + separate front end

Decoupled teams/releases; native mobile clients; a JS framework (React/Angular/Vue) front end

Spring Boot serves JSON only; no server-side view templating needed

JSF (JoinFaces)

Maintaining an existing JSF codebase inside Spring Boot

Legacy choice; not recommended for new projects