JSF
Spring Boot
Custom Component
@FacesComponent
Java

JSF custom component with FacesComponent is not found in Spring Boot

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

When a JSF custom component annotated with @FacesComponent is "not found" in a Spring Boot application, the problem is usually not the component class itself. The real cause is typically one of three things: JSF is not bootstrapped correctly, the project is mixing javax and jakarta APIs, or the component was registered but never exposed as a Facelets tag.

First Check the JSF and Spring Boot Versions

Spring Boot 3 uses Jakarta EE packages, so JSF classes come from jakarta.faces.*. Older JSF examples on the web often use javax.faces.*, which will not work correctly in a Boot 3 application.

If you are on Boot 3, your component should look like this:

java
1package com.example.jsf;
2
3import jakarta.faces.component.FacesComponent;
4import jakarta.faces.component.UIOutput;
5
6@FacesComponent(
7    value = "demo.HelloOutput",
8    createTag = true,
9    namespace = "http://example.com/jsf",
10    tagName = "helloOutput"
11)
12public class HelloOutput extends UIOutput {
13}

If your imports use javax.faces.component.FacesComponent, that suggests an older JSF generation. The code may compile in the wrong dependency setup, but runtime discovery can still fail when the container and annotation package do not match.

Using a JSF starter also matters. In Spring Boot, many teams use JoinFaces so the servlet, lifecycle, and configuration are registered correctly.

xml
1<dependency>
2  <groupId>org.joinfaces</groupId>
3  <artifactId>faces-spring-boot-starter</artifactId>
4</dependency>

Without proper JSF bootstrap, Spring will start, but JSF annotations will not be processed in the way you expect.

@FacesComponent Is a JSF Annotation, Not a Spring One

This point causes a lot of confusion. Spring component scanning does not "activate" @FacesComponent. The annotation is handled by the JSF runtime, not by Spring's bean scanner.

That means adding @Component usually does not solve the underlying problem. You need the JSF runtime to be initialized and scanning its own artifacts. If the app is just a plain Spring MVC app with JSF dependencies on the classpath, Facelets still will not behave correctly unless the Faces servlet and configuration are actually in place.

If you are not using a starter, you typically need explicit servlet registration:

java
1import jakarta.faces.webapp.FacesServlet;
2import org.springframework.boot.web.servlet.ServletRegistrationBean;
3import org.springframework.context.annotation.Bean;
4import org.springframework.context.annotation.Configuration;
5
6@Configuration
7public class JsfConfig {
8    @Bean
9    public ServletRegistrationBean<FacesServlet> facesServlet() {
10        ServletRegistrationBean<FacesServlet> bean =
11            new ServletRegistrationBean<>(new FacesServlet(), "*.xhtml");
12        bean.setLoadOnStartup(1);
13        return bean;
14    }
15}

Once the Faces servlet is active, JSF gets a chance to process components, views, and tag metadata.

Registering the Component as a Tag

Another frequent misunderstanding is that @FacesComponent identifies a component type, but that does not always mean you can immediately write a custom XML tag in your page. For modern JSF versions, createTag = true, namespace, and tagName let JSF expose the component directly to Facelets.

Example usage in an XHTML page:

xhtml
1<html xmlns="http://www.w3.org/1999/xhtml"
2      xmlns:h="jakarta.faces.html"
3      xmlns:demo="http://example.com/jsf">
4  <h:body>
5    <demo:helloOutput value="Hello from custom component" />
6  </h:body>
7</html>

If you omit createTag = true, you may have a valid component type but no usable Facelets tag. In older JSF versions, automatic tag creation is not available, so you need a tag library descriptor instead.

xml
1<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee" version="2.2">
2  <namespace>http://example.com/jsf</namespace>
3  <tag>
4    <tag-name>helloOutput</tag-name>
5    <component>
6      <component-type>demo.HelloOutput</component-type>
7    </component>
8  </tag>
9</facelet-taglib>

That distinction matters because the runtime error often says the tag is unknown, even though the class itself exists.

Packaging and Discovery Tips

Keep the component class in your application's compiled classes, not only in test sources or an excluded module. Also make sure the XHTML page uses the exact namespace you registered. A tiny mismatch in namespace or tag name produces the same "not found" symptom as a broken component.

If the component lives in a shared library, verify that the library is on the runtime classpath and that its JSF metadata is packaged correctly. Spring dependency management may bring in the jar, but JSF still depends on correct runtime visibility and metadata.

Common Pitfalls

  • Mixing javax.faces.* imports with a Spring Boot 3 application that expects jakarta.faces.*.
  • Assuming @FacesComponent is discovered by Spring component scanning.
  • Defining a component type but never exposing it as a Facelets tag.
  • Forgetting to register FacesServlet when not using a JSF starter.
  • Using the wrong XML namespace or tag name in the XHTML page.

Summary

  • In Spring Boot, a missing @FacesComponent usually points to JSF setup problems, not just a bad component class.
  • Match your JSF package names to your Spring Boot generation: jakarta for Boot 3, javax for older stacks.
  • Ensure JSF is actually bootstrapped, either through a starter such as JoinFaces or manual servlet registration.
  • Use createTag = true for modern automatic Facelets tags, or a tag library descriptor on older JSF versions.
  • Verify the runtime namespace, tag name, and packaging before assuming component scanning is broken.

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.