I am currently migrating lot of old code to springboot applications. We have JSF and SOAP web service which migrated successfully. I am facing issue related to WsConfigurerAdapter
. If we enable EndpointInterceptor
then FacesServlet does not initialize properly and throws below error.
15:28:41.045 [http-nio-8080-exec-1] ERROR j.faces - Unable to obtain InjectionProvider from init time FacesContext. Does this container implement the Mojarra Injection SPI?
15:28:41.046 [http-nio-8080-exec-1] ERROR j.faces - Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory. Attempting to find backup.
15:28:41.047 [http-nio-8080-exec-1] ERROR o.a.c.c.C.[.[.[/KSF] - Servlet.init() for servlet [FacesServlet] threw exception
java.lang.IllegalStateException: Could not find backup for factory javax.faces.context.FacesContextFactory.
at javax.faces.FactoryFinderInstance.getFactory(FactoryFinderInstance.java:541) ~[javax.faces-2.3.9.jar!/:2.3.9]
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:292) ~[javax.faces-2.3.9.jar!/:2.3.9]
at javax.faces.webapp.FacesServlet.init(FacesServlet.java:374) ~[javax.faces-2.3.9.jar!/:2.3.9]
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1164) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:804) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:128) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.56.jar!/:?]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_222-4-redhat]
15:28:41.055 [http-nio-8080-exec-1] ERROR o.a.c.c.C.[.[.[.[FacesServlet] - Allocate exception for servlet [FacesServlet]
java.lang.IllegalStateException: Could not find backup for factory javax.faces.context.FacesContextFactory.
at javax.faces.FactoryFinderInstance.getFactory(FactoryFinderInstance.java:541) ~[javax.faces-2.3.9.jar!/:2.3.9]
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:292) ~[javax.faces-2.3.9.jar!/:2.3.9]
at javax.faces.webapp.FacesServlet.init(FacesServlet.java:374) ~[javax.faces-2.3.9.jar!/:2.3.9]
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1164) ~[tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:804) ~[tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:128) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-embed-core-9.0.56.jar!/:?]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.56.jar!/:?]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_222-4-redhat]
Web service configuration code
@EnableWs
@Configuration
public class MyWebServiceConfig {
@Bean
public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
ServletRegistrationBean<MessageDispatcherServlet> servletRegistrationBean = new ServletRegistrationBean<>(servlet, "/Services/*");
servletRegistrationBean.setName("MessageDispatcherServlet");
return servletRegistrationBean;
}
@Bean // this is causing JSF deployment issue
public WsConfigurerAdapter csfWsConfigurerAdapter() {
return new WsConfigurerAdapter() {
@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
if (interceptors == null) {
interceptors = new ArrayList<>();
}
MyPayloadValidatingInterceptor validatingInterceptor = new MyPayloadValidatingInterceptor();
validatingInterceptor.setValidateRequest(true);
validatingInterceptor.setValidateResponse(false);
validatingInterceptor.setSchemas(getSchemas());
try {
validatingInterceptor.afterPropertiesSet();
} catch (Exception e) {}
interceptors.add(validatingInterceptor);
}
};
}
}
I am using prime faces with JSF so important dependency are listed below
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<main.basedir>${project.basedir}/..</main.basedir>
<spring.boot.version>2.6.3</spring.boot.version>
<primefaces.version>5.3</primefaces.version>
<faces.version>2.3.9</faces.version>
</properties>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>${primefaces.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>${faces.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
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>
Faces/JSF Configuration
@Configuration
public class MyJSFConfig implements ServletContextAware, WebMvcConfigurer {
@Bean
public ServletRegistrationBean<FacesServlet> servletRegistrationBean() {
ServletRegistrationBean<FacesServlet> servletRegistrationBean = new ServletRegistrationBean<>(
new FacesServlet(), "*.jsf", "*.xhtml");
servletRegistrationBean.setName("FacesServlet");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}
@Bean
public ServletListenerRegistrationBean<ConfigureListener> jsfConfigureListener() {
return new ServletListenerRegistrationBean<ConfigureListener>(new ConfigureListener());
}
@Override
public void setServletContext(ServletContext servletContext) {
// spring boot only works if this is set
// Iniciar el contexto de JSF
// http://stackoverflow.com/a/25509937/1199132
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", Boolean.TRUE.toString());
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/my").setViewName("forward:/my/index.jsf");
}
I am thinking this is classloading issue for springboot. WsConfigurerAdapter is used DelegatingWsConfiguration and configured conditional on missing bean in WebServicesAutoConfiguration. We are on latest springboot release