Undertow 可以与 JSF 一起使用吗?
Does Undertow work with JSF?
我正在尝试使用 Mojarra 启动 Undertow,但出现异常。
如何修复此错误并使用 JSF?
,但是这个方案对我的没有影响
HelloWorldServer.java
(参考 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.call (DeploymentManagerImpl.java:584)
at io.undertow.servlet.core.DeploymentManagerImpl.call (DeploymentManagerImpl.java:555)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction.call (ServletRequestContextThreadSetupAction.java:42)
at io.undertow.servlet.core.ContextClassLoaderSetupAction.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.run (ExecJavaMojo.java:282)
at java.lang.Thread.run (Thread.java:844)
请勿使用 Mojarra 2.4.0 尚未,截至发帖时尚未发布。它必须放在 maven 中才能从 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 由 AnnotationScanTask
with DelegatingAnnotationProvider
扫描,这是默认的 AnnotationProvider
实现。
因为 DelegatingAnnotationProvider
不扫描根 class 路径(但只扫描 /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
我正在尝试使用 Mojarra 启动 Undertow,但出现异常。 如何修复此错误并使用 JSF?
HelloWorldServer.java
(参考 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.call (DeploymentManagerImpl.java:584)
at io.undertow.servlet.core.DeploymentManagerImpl.call (DeploymentManagerImpl.java:555)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction.call (ServletRequestContextThreadSetupAction.java:42)
at io.undertow.servlet.core.ContextClassLoaderSetupAction.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.run (ExecJavaMojo.java:282)
at java.lang.Thread.run (Thread.java:844)
请勿使用 Mojarra 2.4.0 尚未,截至发帖时尚未发布。它必须放在 maven 中才能从 Oracle 过渡到 Eclipse。
http://balusc.omnifaces.org/2018/04/do-not-use-orgglassfish-mojarra-240.html
因此请使用最新的 2.3.x 版本(撰写本文时为 2.3.5)
实现方式与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 由 AnnotationScanTask
with DelegatingAnnotationProvider
扫描,这是默认的 AnnotationProvider
实现。
因为 DelegatingAnnotationProvider
不扫描根 class 路径(但只扫描 /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