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>© 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 |
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 |