我正在尝试用Mojarra启动Undertow,但发生了异常。 如何修复此错误并使用 JSF?
这是类似的问题,但这个解决方案不会影响我的。
HelloWorldServer.java
(refs Undertow Servlet(:
public class HelloWorldServer {
public static void main(String[] args) throws ServletException {
DeploymentInfo servletBuilder = Servlets.deployment()
.setClassLoader(HelloWorldServer.class.getClassLoader())
.setContextPath("/myapp")
.setDeploymentName("test.war")
.addServlets(Servlets.servlet("FacesServlet", FacesServlet.class)
.addMapping("*.xhtml")
.setLoadOnStartup(1));
DeploymentManager manager = Servlets.defaultContainer().addDeployment(servletBuilder);
manager.deploy();
PathHandler path = Handlers.path(Handlers.redirect("/myapp"))
.addPrefixPath("/myapp", manager.start());
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(path)
.build();
server.start();
}
}
pom.xml
:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<undertow.version>2.0.9.Final</undertow.version>
</properties>
<dependencies>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<version>${undertow.version}</version>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
<version>${undertow.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.3.5</version>
</dependency>
</dependencies>
例外:
Jul 07, 2018 9:57:50 PM javax.faces.FactoryFinderInstance copyInjectionProviderFromFacesContext
SEVERE: Unable to obtain InjectionProvider from init time FacesContext. Does this container implement the Mojarra Injection SPI?
Jul 07, 2018 9:57:50 PM javax.faces.FactoryFinderInstance logNoFactory
SEVERE: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory. Attempting to find backup.
[WARNING]
java.lang.IllegalStateException: Could not find backup for factory javax.faces.context.FacesContextFactory.
at javax.faces.FactoryFinderInstance.notNullFactory (FactoryFinderInstance.java:548)
at javax.faces.FactoryFinderInstance.getFactory (FactoryFinderInstance.java:231)
at javax.faces.FactoryFinder.getFactory (FactoryFinder.java:303)
at javax.faces.webapp.FacesServlet.acquireFacesContextFactory (FacesServlet.java:524)
at javax.faces.webapp.FacesServlet.init (FacesServlet.java:364)
at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed (LifecyleInterceptorInvocation.java:117)
at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start (ManagedServlet.java:300)
at io.undertow.servlet.core.ManagedServlet.createServlet (ManagedServlet.java:140)
at io.undertow.servlet.core.DeploymentManagerImpl$2.call (DeploymentManagerImpl.java:584)
at io.undertow.servlet.core.DeploymentManagerImpl$2.call (DeploymentManagerImpl.java:555)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call (ServletRequestContextThreadSetupAction.java:42)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call (ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.core.DeploymentManagerImpl.start (DeploymentManagerImpl.java:597)
at com.github.yukihane.java.undertow.HelloWorldServer.main (HelloWorldServer.java:27)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:564)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:282)
at java.lang.Thread.run (Thread.java:844)
不要使用 Mojarra 2.4.0YET,截至本文发布时尚未发布。它必须放在从Oracle到Eclipse的过渡中。
http://balusc.omnifaces.org/2018/04/do-not-use-orgglassfish-mojarra-240.html
因此,请使用最新的2.3.x版本(撰写本文时为2.3.5(
1.实现与 FacesInitializer#onStartup 相同,因此main
方法如下所示:
DeploymentInfo servletBuilder = Servlets.deployment()
.setClassLoader(HelloWorldServer.class.getClassLoader())
.setContextPath("/myapp")
.setDeploymentName("test.war")
.addServlets(Servlets.servlet("FacesServlet", FacesServlet.class)
.addMappings("/faces/*", "*.jsf", "*.faces", "*.xhtml")
.setLoadOnStartup(1))
.addServletContextAttribute(RIConstants.FACES_INITIALIZER_MAPPINGS_ADDED, Boolean.TRUE)
.addListener(new ListenerInfo(com.sun.faces.config.ConfigureListener.class))
.setResourceManager(new ClassPathResourceManager(HelloWorldServer.class.getClassLoader(), "static"));
2.受管 Bean 通过DelegatingAnnotationProvider
AnnotationScanTask
扫描,这是缺省AnnotationProvider
实现。 因为DelegatingAnnotationProvider
不扫描根类路径(而只扫描/WEB-INF/classes
(?((,所以我需要实现自定义AnnotationProvider
。
MyAnnotationProvider.java
:
package com.github.yukihane.java.undertow.service;
public class MyAnnotationProvider extends DelegatingAnnotationProvider {
public MyAnnotationProvider(ServletContext sc) {
super(sc);
}
@Override
public Map<Class<? extends Annotation>, Set<Class<?>>> getAnnotatedClasses(Set<URI> urls) {
Map<Class<? extends Annotation>, Set<Class<?>>> parentRes = super.getAnnotatedClasses(urls);
// simplified implementation, without annotations scan
Map<Class<? extends Annotation>, Set<Class<?>>> ret = new HashMap<>(parentRes);
Set<Class<?>> parentSet = ret.get(ManagedBean.class);
Set<Class<?>> set = (parentSet == null) ? new HashSet<>() : new HashSet<>(parentSet);
set.add(Hello.class);
ret.put(ManagedBean.class, set);
return ret;
}
}
META-INF/services/com.sun.faces.spi.annotationprovider
(参考文献AnnotationProviderFactory
(:
com.github.yukihane.java.undertow.service.MyAnnotationProvider
以下是完整的来源: https://github.com/yukihane/hello-undertow-mojarra