Reputation: 85
I'm trying to create a JSF project managed by Spring boot 3.0. But it doesn't work no matter how I do it. I can't find any example on the web.
My dependencies:
implementation 'org.springframework.boot:spring-boot-starter-web:3.0.2'
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper:10.1.5'
implementation 'org.glassfish:jakarta.faces:4.0.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.0.2'
My MainApplication class:
@SpringBootApplication
public class ManagementClientApplication implements ServletContextAware {
public static void main(String[] args) {
SpringApplication.run(ManagementClientApplication.class, args);
}
@Bean
public ServletRegistrationBean<FacesServlet> servletRegistrationBean() {
ServletRegistrationBean<FacesServlet> servletRegistrationBean = new ServletRegistrationBean<>(new FacesServlet(), "*.xhtml");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}
@Override
public void setServletContext(ServletContext servletContext) {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
servletContext.setInitParameter("jakarta.faces.FACELETS_SKIP_COMMENTS", "true");
}
}
My config webapp/WEB-INF/faces-config.xml :
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
</faces-config>
A test XHTML file:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
</h:head>
<h:body>
<h:form>
<h:outputText id="greeting" value="Hello world !" />
</h:form>
</h:body>
</html>
Logs :
2023-02-02T17:21:10.844+01:00 INFO 6312 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-02-02T17:21:10.845+01:00 INFO 6312 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 738 ms
2023-02-02T17:21:11.133+01:00 ERROR 6312 --- [ main] jakarta.faces : Unable to obtain InjectionProvider from init time FacesContext. Does this container implement the Mojarra Injection SPI?
2023-02-02T17:21:11.149+01:00 ERROR 6312 --- [ main] jakarta.faces : L’application n’a pas été initialisée correctement au démarrage. Impossible de localiser la Fabrique : jakarta.faces.context.FacesContextFactory. Attempting to find backup.
2023-02-02T17:21:11.150+01:00 ERROR 6312 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Servlet.init() for servlet [facesServlet] threw exception
java.lang.IllegalStateException: Could not find backup for factory jakarta.faces.context.FacesContextFactory.
at jakarta.faces.FactoryFinderInstance.notNullFactory(FactoryFinderInstance.java:497) ~[jakarta.faces-4.0.1.jar:4.0.1]
at jakarta.faces.FactoryFinderInstance.getFactory(FactoryFinderInstance.java:190) ~[jakarta.faces-4.0.1.jar:4.0.1]
at jakarta.faces.FactoryFinder.getFactory(FactoryFinder.java:263) ~[jakarta.faces-4.0.1.jar:4.0.1]
at jakarta.faces.webapp.FacesServlet.acquireFacesContextFactory(FacesServlet.java:493) ~[jakarta.faces-4.0.1.jar:4.0.1]
Links I looked at:
How to properly configure Jakarta EE libraries in Maven pom.xml for Tomcat? Spring Boot JSF Integration
The project with Spring boot 2 and Javax that I tried to reproduce:
https://github.com/xtremebiker/jsf-spring-boot
I don't understand what I'm doing wrong. I can't find anything on the web. Any help would be welcome.
Thank you all
Upvotes: 7
Views: 5735
Reputation: 1106
You can use the JoinFaces starter.
As written on Mojarra, you need more dependencies.
implementation group: 'org.jboss.weld.servlet', name: 'weld-servlet-shaded', version: '5.1.0.Final'
Don't create FacesServlet yourself. ServletContainerInitializer
does that.
But if you use embedded server, you should run two of them. Because Spring Boot doesn't run the initializers.
@Bean
public ServletContextInitializer facesInitializer() {
return new JsfInitializer();
}
import org.jboss.weld.environment.servlet.EnhancedListener;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import jakarta.servlet.ServletContainerInitializer;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import com.sun.faces.config.FacesInitializer;
public class JsfInitializer implements ServletContextInitializer {
@Override
public void onStartup(ServletContext context) throws ServletException {
EnhancedListener cdiInitializer = new EnhancedListener();
cdiInitializer.onStartup(null, context);
ServletContainerInitializer facesInitializer = new FacesInitializer();
facesInitializer.onStartup(null, context);
}
}
After packaging to jar with Spring Boot, you get problems with CDI and static resources. I know 3 variants to fix this.
org.jboss.weld.environment.deployment.discovery.BeanArchiveHandler
and register to META-INF/services
.context.getResources().createWebResourceSet(ResourceSetType.RESOURCE_JAR, "/", jarRoot, "/META-INF/resources");
Upvotes: 2
Reputation: 11
Try:
implementation 'org.glassfish:jakarta.faces:3.0.4'
I did not figure out the root cause (conflict?) yet but, I have noticed that any versions above 3.0.4 cause the exception you are getting. I got the same. This worked for me:
implementation 'org.springframework.boot:spring-boot-starter-web:3.0.1'
implementation 'org.glassfish:jakarta.faces:3.0.4'
providedRuntime 'org.apache.tomcat.embed:tomcat-embed-jasper:11.0.0-M6'
Upvotes: 1