Search code examples
javaspring-bootrichfacesweb.xml

Richfaces 3.x - Spring Boot - Migrate web.xml


I've been struggling with this for a few days to migrate an old Spring with standalone tomcat server to SpringBoot (1.5.22.RELEASE) with embedded tomcat server and not sure what exactly I've done wrong as I still can't get it to boot.

This was how the web.xml looked like (located in src/main/webapp/WEB-INF):

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>

    <context-param>
        <param-name>facelets.REFRESH_PERIOD</param-name>
        <param-value>1</param-value>
    </context-param>

    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
    </context-param>

    <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>facelets.SKIP_COMMENTS</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>facelets.LIBRARIES</param-name>
        <param-value>/WEB-INF/facelets/custom.taglib.xml</param-value>
    </context-param>

    <context-param>
        <param-name>com.sun.faces.preferXHTML</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>com.sun.faces.expressionFactory</param-name>
        <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/META-INF/spring/root-context.xml
        </param-value>
    </context-param>

    <context-param>
        <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
        <param-value>com.sun.facelets.FaceletViewHandler</param-value>
    </context-param>

    <context-param>
        <param-name>org.richfaces.SKIN</param-name>
        <param-value>blueSky</param-value>
    </context-param>

    <context-param>
        <param-name>org.richfaces.CONTROL_SKINNING</param-name>
        <param-value>enable</param-value>
    </context-param>        <context-param>
        <param-name>log4jRefreshInterval</param-name>
        <param-value>1000</param-value>
    </context-param>

    <filter>
        <filter-name>richfaces</filter-name>
        <display-name>RichFaces Filter</display-name>
        <filter-class>org.ajax4jsf.Filter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>richfaces</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>

    <filter>
        <filter-name>openEntityManagerInViewFilter</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>openEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>rest</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>rest</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/META-INF/spring/root-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/service/*</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>MyService.xhtml</welcome-file>
    </welcome-file-list> </web-app>

After a lot of googling I ended up settling for implementing the ServletContextInitializer:

@Configuration
public class WebConfiguration implements ServletContextInitializer {
    private static final String FACES_SERVLET = "Faces Servlet";

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
        
        TomcatContextCustomizer contextCustomizer = context -> context.addWelcomeFile("/MyService.xhtml");
        factory.addContextCustomizers(contextCustomizer);
        
        return factory;
    }
    
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        
        // Parameters
        servletContext.setInitParameter("javax.faces.STATE_SAVING_METHOD", "client");
        servletContext.setInitParameter("facelets.REFRESH_PERIOD", "1");
        servletContext.setInitParameter("com.sun.faces.validateXml", "true");
        servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
        servletContext.setInitParameter("facelets.DEVELOPMENT", "true");
        servletContext.setInitParameter("facelets.SKIP_COMMENTS", "true");
        servletContext.setInitParameter("facelets.LIBRARIES", "/WEB-INF/facelets/custom.taglib.xml");
        servletContext.setInitParameter("com.sun.faces.preferXHTML", "true");
        servletContext.setInitParameter("com.sun.faces.expressionFactory", "com.sun.el.ExpressionFactoryImpl");
        servletContext.setInitParameter("org.ajax4jsf.VIEW_HANDLERS", "com.sun.facelets.FaceletViewHandler");
        servletContext.setInitParameter("org.richfaces.SKIN", "blueSky");
        servletContext.setInitParameter("org.richfaces.CONTROL_SKINNING", "enable");
        servletContext.setInitParameter("log4jRefreshInterval", "1000");
        
        // Filters
        FilterRegistration.Dynamic richfacesFilter = servletContext.addFilter("richfaces", Filter.class);
        EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE);
        richfacesFilter.addMappingForServletNames(dispatcherTypes, true, FACES_SERVLET);
        
        FilterRegistration.Dynamic openEntityManagerInViewFilter = servletContext.addFilter("openEntityManagerInViewFilter", OpenEntityManagerInViewFilter.class);
        openEntityManagerInViewFilter.addMappingForUrlPatterns(null, true, "/*");
        
        // Listeners
        servletContext.addListener(new ContextLoaderListener(rootContext));
        servletContext.addListener(new RequestContextListener());
        servletContext.addListener(new Log4jConfigListener());
        
        // Servlet
        ServletRegistration.Dynamic restServlet = servletContext.addServlet("rest", new DispatcherServlet(rootContext));
        restServlet.setLoadOnStartup(1);
        restServlet.addMapping("/rest/*");
        
        ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(rootContext));
        dispatcherServlet.setLoadOnStartup(1);
        dispatcherServlet.setInitParameter("contextAttribute", "org.springframework.web.context.WebApplicationContext.ROOT");
        dispatcherServlet.addMapping("/");
        
        ServletRegistration.Dynamic facesServlet = servletContext.addServlet(FACES_SERVLET, new FacesServlet());
        facesServlet.setLoadOnStartup(1);
        facesServlet.addMapping("*.xhtml", "*.html", "/faces/*", "*.faces");
    }
}

Now to my problems, first and foremost is the listeners, as following errors are thrown during startup:

ERROR --- [ost-startStop-1] o.a.c.c.C.[.[.[/].log:182 - Exception sending context initialized event to listener instance of class [org.springframework.web.context.ContextLoaderListener]
java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:296)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4697)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5165)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)
ERROR --- [ost-startStop-1] o.a.c.c.C.[.[.[/].log:182 - Exception sending context initialized event to listener instance of class [org.springframework.web.util.Log4jConfigListener]
java.lang.IllegalStateException: Cannot set web app root system property when WAR file is not expanded
        at org.springframework.web.util.WebUtils.setWebAppRootSystemProperty(WebUtils.java:156)
        at org.springframework.web.util.Log4jWebConfigurer.initLogging(Log4jWebConfigurer.java:119)
        at org.springframework.web.util.Log4jConfigListener.contextInitialized(Log4jConfigListener.java:49)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4697)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5165)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)
ERROR --- [ost-startStop-1] o.a.c.c.StandardContext.log:180 - One or more listeners failed to start. Full details will be found in the appropriate container log file
ERROR --- [ost-startStop-1] o.a.c.c.StandardContext.log:180 - Context [] startup failed due to previous errors
INFO --- [ost-startStop-1] o.a.c.c.C.[.[.[/].log:180 - Shutting down log4j
ERROR --- [ost-startStop-1] o.a.c.c.C.[.[.[/].log:182 - Exception sending context destroyed event to listener instance of class [org.springframework.web.util.Log4jConfigListener]
java.lang.NoClassDefFoundError: org/apache/log4j/LogManager
        at org.springframework.util.Log4jConfigurer.shutdownLogging(Log4jConfigurer.java:123)
        at org.springframework.web.util.Log4jWebConfigurer.shutdownLogging(Log4jWebConfigurer.java:172)
        at org.springframework.web.util.Log4jConfigListener.contextDestroyed(Log4jConfigListener.java:54)
        at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4744)
        at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5403)
        at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.LogManager
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351)

I figured SpringBoot already runs a ContextLoaderListener so I removed it and also removed the Log4jConfigListener after reading about the issue here: SEVERE: Exception org.springframework.web.util.Log4jConfigListener

Now it boots further but gets stuck on here:

ERROR --- [           main] o.a.c.c.C.[.[.[/].log:182 - StandardWrapper.Throwable
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
        at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
        at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
        at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1132)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:976)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4885)
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedContext.deferredLoadOnStartup(TomcatEmbeddedContext.java:77)
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.performDeferredLoadOnStartup(TomcatEmbeddedServletContainer.java:279)
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.start(TomcatEmbeddedServletContainer.java:206)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.startEmbeddedServletContainer(EmbeddedWebApplicationContext.java:289)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:145)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:123)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:666)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:353)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:300)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1082)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1071)
        at com.foo.Application.main(Application.java:18)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
        at org.springframework.boot.loader.WarLauncher.main(WarLauncher.java:59)
ERROR --- [           main] o.a.c.c.C.[.[.[/].log:182 - Servlet [Faces Servlet] in web application [] threw load() exception
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
        at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
        at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
        at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1132)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:976)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4885)
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedContext.deferredLoadOnStartup(TomcatEmbeddedContext.java:77)
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.performDeferredLoadOnStartup(TomcatEmbeddedServletContainer.java:279)
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.start(TomcatEmbeddedServletContainer.java:206)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.startEmbeddedServletContainer(EmbeddedWebApplicationContext.java:289)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:145)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:123)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:666)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:353)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:300)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1082)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1071)
        at com.foo.Application.main(Application.java:18)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
        at org.springframework.boot.loader.WarLauncher.main(WarLauncher.java:59)

Can't remember where I found it but I saw a recommendation that adding com.sun.faces.config.ConfigureListener as a listenr would resolve it. This was enough to get the application to boot without any errors however trying to access the web-ui I now run into issues with the filters:

ERROR --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].log:182 - StandardWrapper.Throwable
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
        at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
        at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
        at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1132)
        at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:779)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:134)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)
ERROR --- [nio-8080-exec-3] o.a.c.c.C.[.[.[.[Faces Servlet].log:182 - Allocate exception for servlet [Faces Servlet]
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
        at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
        at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
        at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1132)
        at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:779)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:134)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)
        

Trying to run without filters just to see if it can boot if I can resolve them I finally lands on this error where I'm currently am at:

ERROR --- [nio-8080-exec-1] f.viewhandler.handleRenderException:667 - Error Rendering View[/login.xhtml]
javax.faces.FacesException: Resources framework is not initialised, check web.xml for Filter configuration
        at org.ajax4jsf.resource.ResourceBuilderImpl.getWebXml(ResourceBuilderImpl.java:118)
        at org.ajax4jsf.resource.ResourceBuilderImpl.getUri(ResourceBuilderImpl.java:325)
        at org.ajax4jsf.resource.InternetResourceBase.getUri(InternetResourceBase.java:218)
        at org.richfaces.renderkit.html.MenuItemRendererBase.initializeResources(MenuItemRendererBase.java:188)
        at org.richfaces.renderkit.html.MenuItemRenderer.doEncodeEnd(MenuItemRenderer.java:191)
        at org.richfaces.renderkit.html.MenuItemRenderer.doEncodeEnd(MenuItemRenderer.java:319)
        at org.ajax4jsf.renderkit.RendererBase.encodeEnd(RendererBase.java:134)
        at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:861)
        at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:281)
        at org.richfaces.renderkit.html.AbstractMenuRenderer.encodeItems(AbstractMenuRenderer.java:279)
        at org.richfaces.renderkit.html.AbstractMenuRenderer.processLayer(AbstractMenuRenderer.java:246)
        at org.richfaces.renderkit.html.AbstractMenuRenderer.encodeChildren(AbstractMenuRenderer.java:219)
        at org.richfaces.renderkit.html.DropDownMenuRendererBase.encodeChildren(DropDownMenuRendererBase.java:62)
        at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
        at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:277)
        at org.richfaces.renderkit.html.ToolBarGroupRenderer.renderChild(ToolBarGroupRenderer.java:74)
        at org.richfaces.renderkit.html.ToolBarGroupRenderer.encodeChildren(ToolBarGroupRenderer.java:56)
        at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
        at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:277)
        at org.richfaces.renderkit.html.ToolBarRendererBase.encodeChildren(ToolBarRendererBase.java:103)
        at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:930)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:933)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:933)
        at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:578)
        at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
        at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
        at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
        at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)

    

This seems to almost work as I can see a lot of libraries being loaded and the page does try to render but what exactly it's missing I've got no clue.


Solution

  • Noticed that WebXml.java from the richface package was being executed under the surface which seems to require an web.xml to read properties from. Couldn't find any replacement classes for it so I left the faces components in the web.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             version="2.5">
        <!-- TODO - Not used by SpringBoot! But needed for richface 3.x with faces components for WebXml.java to set properties correctly -->
        <filter>
            <filter-name>richfaces</filter-name>
            <display-name>RichFaces Filter</display-name>
            <filter-class>org.ajax4jsf.Filter</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>richfaces</filter-name>
            <servlet-name>Faces Servlet</servlet-name>
            <dispatcher>REQUEST</dispatcher>
            <dispatcher>FORWARD</dispatcher>
            <dispatcher>INCLUDE</dispatcher>
        </filter-mapping>
    
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.xhtml</url-pattern>
        </servlet-mapping>
    
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.html</url-pattern>
        </servlet-mapping>
    
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>/faces/*</url-pattern>
        </servlet-mapping>
    
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.faces</url-pattern>
        </servlet-mapping>
    </web-app>
    

    But also migrated (and stripped unnecessary components now when it's boot-ified) the following to WebConfiguration:

    public class WebConfiguration implements ServletContextInitializer {
        private static final String FACES_SERVLET = "Faces Servlet";
        
        @Bean
        public EmbeddedServletContainerFactory servletContainer() {
            TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
            
            TomcatContextCustomizer contextCustomizer = context -> context.addWelcomeFile("/MyService.xhtml");
            factory.addContextCustomizers(contextCustomizer);
            
            return factory;
        }
        
        @Override
        public void onStartup(ServletContext servletContext) {
            AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
            
            // Parameters
            servletContext.setInitParameter("javax.faces.STATE_SAVING_METHOD", "client");
            servletContext.setInitParameter("facelets.REFRESH_PERIOD", "1");
            servletContext.setInitParameter("com.sun.faces.validateXml", "true");
            servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
            servletContext.setInitParameter("facelets.DEVELOPMENT", "true");
            servletContext.setInitParameter("facelets.SKIP_COMMENTS", "true");
            servletContext.setInitParameter("facelets.LIBRARIES", "/WEB-INF/facelets/custom.taglib.xml");
            servletContext.setInitParameter("com.sun.faces.preferXHTML", "true");
            servletContext.setInitParameter("com.sun.faces.expressionFactory", "com.sun.el.ExpressionFactoryImpl");
            servletContext.setInitParameter("org.ajax4jsf.VIEW_HANDLERS", "com.sun.facelets.FaceletViewHandler");
            servletContext.setInitParameter("org.richfaces.SKIN", "blueSky");
            servletContext.setInitParameter("org.richfaces.CONTROL_SKINNING", "enable");
            servletContext.setInitParameter("log4jRefreshInterval", "1000");
            
            // Filters
            servletContext
               .addFilter("richfaces", new Filter())
               .addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, FACES_SERVLET);
            
            servletContext
               .addFilter("openEntityManagerInViewFilter", new OpenEntityManagerInViewFilter())
               .addMappingForUrlPatterns(null, false, "/*");
            
            // Listeners
            servletContext.addListener(new RequestContextListener());
            servletContext.addListener(new ConfigureListener());
            
            // Servlets
            ServletRegistration.Dynamic restServlet = servletContext.addServlet("rest", new DispatcherServlet(rootContext));
            restServlet.setLoadOnStartup(1);
            restServlet.addMapping("/rest/*");
            
            ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(rootContext));
            dispatcherServlet.setLoadOnStartup(1);
            dispatcherServlet.setInitParameter("contextAttribute", "org.springframework.web.context.WebApplicationContext.ROOT");
            dispatcherServlet.addMapping("/");
            
            ServletRegistration.Dynamic facesServlet = servletContext.addServlet(FACES_SERVLET, new FacesServlet());
            facesServlet.setLoadOnStartup(1);
            facesServlet.addMapping("*.xhtml", "*.html", "/faces/*", "*.faces");
        }
    }
    

    Might be able to go entirely without a web.xml if I upgrade the richface to 4.x or even 5.x but don't have time to test that currently.