Spring Boot
JSF
Integration
Java
Web Development

Spring Boot JSF Integration

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Spring Boot and JSF can work together, but the integration is not as automatic as a typical Spring MVC application. JSF is a component-based servlet framework, so the main job is wiring the FacesServlet, Facelets pages, and bean resolution into Boot’s embedded servlet container.

Understand the Architecture First

JSF is not a replacement for Spring Boot. Boot gives you packaging, dependency management, auto-configuration, and the embedded servlet container. JSF handles the server-rendered UI layer.

That means a typical integrated app looks like this:

  • Spring Boot starts the application
  • the embedded servlet container hosts JSF
  • JSF renders .xhtml pages
  • Spring beans provide services and business logic

This setup makes sense when you already want a JSF server-side component model. If you are building a REST API or a reactive UI backend, JSF is usually the wrong tool.

Add the Required Dependencies

At minimum you need the Boot web starter and a JSF implementation. With Spring Boot 3 style applications, use Jakarta packages rather than the older javax names.

xml
1<dependencies>
2  <dependency>
3    <groupId>org.springframework.boot</groupId>
4    <artifactId>spring-boot-starter-web</artifactId>
5  </dependency>
6  <dependency>
7    <groupId>org.glassfish</groupId>
8    <artifactId>jakarta.faces</artifactId>
9  </dependency>
10</dependencies>

Many teams use a starter such as JoinFaces to reduce boilerplate. The manual setup below is useful because it makes the moving parts explicit.

Register the FacesServlet

Boot does not expose JSF pages until the JSF servlet is registered.

java
1package com.example.demo;
2
3import jakarta.faces.webapp.FacesServlet;
4import org.springframework.boot.SpringApplication;
5import org.springframework.boot.autoconfigure.SpringBootApplication;
6import org.springframework.boot.web.servlet.ServletContextInitializer;
7import org.springframework.boot.web.servlet.ServletRegistrationBean;
8import org.springframework.context.annotation.Bean;
9
10@SpringBootApplication
11public class DemoApplication {
12
13    public static void main(String[] args) {
14        SpringApplication.run(DemoApplication.class, args);
15    }
16
17    @Bean
18    ServletRegistrationBean<FacesServlet> facesServletRegistration() {
19        ServletRegistrationBean<FacesServlet> registration =
20            new ServletRegistrationBean<>(new FacesServlet(), "*.xhtml");
21        registration.setLoadOnStartup(1);
22        return registration;
23    }
24
25    @Bean
26    ServletContextInitializer facesInitializer() {
27        return servletContext -> {
28            servletContext.setInitParameter("jakarta.faces.PROJECT_STAGE", "Development");
29            servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", "true");
30        };
31    }
32}

This tells Boot to serve JSF requests through FacesServlet for .xhtml pages.

Expose Spring Beans to JSF EL

JSF pages commonly access beans through expression language such as #{greetingBean}. To resolve Spring-managed beans that way, add a JSF EL resolver in faces-config.xml.

xml
1<?xml version="1.0" encoding="UTF-8"?>
2<faces-config
3    version="4.0"
4    xmlns="https://jakarta.ee/xml/ns/jakartaee"
5    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6    xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-facesconfig_4_0.xsd">
7  <application>
8    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
9  </application>
10</faces-config>

Then define a Spring bean:

java
1package com.example.demo;
2
3import org.springframework.stereotype.Component;
4import org.springframework.web.context.annotation.RequestScope;
5
6@Component("greetingBean")
7@RequestScope
8public class GreetingBean {
9
10    private String name = "Spring Boot";
11
12    public String getName() {
13        return name;
14    }
15
16    public void setName(String name) {
17        this.name = name;
18    }
19
20    public String getMessage() {
21        return "Hello, " + name;
22    }
23}

Create a Facelets Page

A minimal src/main/webapp/index.xhtml can render and bind to that bean:

xhtml
1<!DOCTYPE html>
2<html xmlns="http://www.w3.org/1999/xhtml"
3      xmlns:h="jakarta.faces.html">
4<h:head>
5    <title>JSF on Spring Boot</title>
6</h:head>
7<h:body>
8    <h:form>
9        <h:outputLabel for="name" value="Name" />
10        <h:inputText id="name" value="#{greetingBean.name}" />
11        <h:commandButton value="Refresh" />
12    </h:form>
13
14    <h:outputText value="#{greetingBean.message}" />
15</h:body>
16</html>

At that point, Boot is hosting a JSF page backed by a Spring-managed bean.

Practical Constraints

There are a few rules that keep this sane:

  • stay on the servlet stack, not WebFlux
  • prefer jakarta.* APIs in modern Spring Boot applications
  • keep your service layer in ordinary Spring beans
  • treat JSF as the view layer, not as the whole application architecture

This matters because JSF integration becomes messy when you blur framework responsibilities.

Common Pitfalls

The biggest mistake is forgetting that JSF needs a servlet registration. Adding the dependency alone does not make .xhtml pages start working.

Another mistake is mixing old javax.faces era examples into a Jakarta-based Boot application. The package names and compatibility story changed.

Developers also often forget EL resolution for Spring beans, which leads to pages failing to resolve #{...} expressions even though the Spring bean exists.

Finally, JSF is not a good fit for every Boot project. If the app is mostly JSON APIs or modern front-end integration, Spring MVC controllers or REST endpoints are usually a better choice than forcing JSF into the stack.

Summary

  • Spring Boot can host JSF, but the integration requires explicit servlet and bean-resolution setup.
  • In modern applications, use Jakarta JSF packages rather than old javax examples.
  • Register FacesServlet, configure faces-config.xml, and expose Spring beans through an EL resolver.
  • Keep Spring services as normal Spring beans and let JSF handle only the UI layer.
  • Use this integration when you genuinely want server-rendered JSF pages, not as a default web stack choice.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.