Bean 验证不适用于 mojarra 2.2.4
Posted
技术标签:
【中文标题】Bean 验证不适用于 mojarra 2.2.4【英文标题】:Bean validation doesn't work with mojarra 2.2.4 【发布时间】:2013-11-07 09:56:27 【问题描述】:我正在尝试使用 Hibernate Validator 5.0.1 和 JSF2.2,但自 mojarra 版本 2.2.3 以来它们的集成似乎被破坏了。我创建了一个小应用程序来演示这个问题并得到异常“javax.servlet.ServletException:Expression Error: Named Object: javax.faces.Bean not found”。在 Tomcat 7.0.42 上运行时。
还有其他人有这个问题吗?
webapp/pages/index.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:body>
<h:form>
<h:messages/>
<h:inputText value="#theBean.z">
<f:validateBean/>
</h:inputText>
<h:commandButton value="send z"/>
</h:form>
</h:body>
</html>
TheBean.java
package lo.test;
import javax.faces.bean.ManagedBean;
import javax.validation.constraints.Min;
@ManagedBean
public class TheBean
@Min(5)
private Integer z;
public Integer getZ()
return z;
public void setZ(Integer z)
this.z = z;
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
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_3_0.xsd"
version="3.0">
<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>
<welcome-file-list>
<welcome-file>pages/index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
依赖关系:
"org.hibernate:hibernate-validator:5.0.1.Final"
"com.sun.faces:jsf-impl:2.2.4"
"com.sun.faces:jsf-api:2.2.4"
异常的完整堆栈跟踪:
javax.faces.FacesException: Expression Error: Named Object: javax.faces.Bean not found.
at com.sun.faces.application.ApplicationImpl.createValidator(ApplicationImpl.java:1596)
at com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.createValidator(ValidatorTagHandlerDelegateImpl.java:245)
at com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.applyAttachedObject(ValidatorTagHandlerDelegateImpl.java:133)
at com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.applyNested(ValidatorTagHandlerDelegateImpl.java:212)
at com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.apply(ValidatorTagHandlerDelegateImpl.java:88)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:190)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:95)
at com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:93)
at com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:87)
at com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:161)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.buildView(FaceletViewHandlingStrategy.java:980)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:99)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
【问题讨论】:
您还可以添加完整的堆栈跟踪吗? 我在休眠验证器 5.0.1 和 Mojarra >= 2.2.3 中遇到了同样的问题。 2.2.2 也适合我。 【参考方案1】:Mojarra 2.2.3 到 2.2.6 在 Tomcat 或 Jetty 等 servlet 容器上似乎会出现问题,因为 Mojarra 尝试通过 JNDI 加载 bean 验证。
我在 JavaLand 2014 上与 Ed Burns 讨论了这个问题,应该使用 Mojarra 2.2.7 解决这个问题(请参阅 JAVASERVERFACES-3183)。
【讨论】:
【参考方案2】:检查以下内容:
ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
applicationFactory.getApplication().addDefaultValidatorId(BeanValidator.VALIDATOR_ID);
applicationFactory.getApplication().addValidator(BeanValidator.VALIDATOR_ID, BeanValidator.class.getName());
【讨论】:
使用 Tomcat Tomcat 6.0.39、JSF 2.2.6 和 Hibernate Bean Validator 4.3.1 为我工作 是的,我也是!这个 bug 快把我逼疯了,我很确定它一定是 JSF 中的许多 bug 之一(叹气!)使用 Tomcat 7.0.53、JSF 2.2.6 和 Hibernate Bean Validator 5.1.1 – Kounavi【参考方案3】:这适用于 Mojara 2.2.2,但不适用于较新的版本。感谢 Michail 的提示。这是另一种预配置 Faces 的方法:
public class FacesContextBootstrap implements ServletContextListener
public static final String BEANS_VALIDATION_AVAILABILITY_CACHE_KEY = "javax.faces.BEANS_VALIDATION_AVAILABLE";
@Override
public void contextInitialized(ServletContextEvent sce)
FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().remove(BEANS_VALIDATION_AVAILABILITY_CACHE_KEY);
FacesContext.getCurrentInstance().getExternalContext().getApplicationMap()
.put(BeanValidator.VALIDATOR_FACTORY_KEY, Validation.buildDefaultValidatorFactory());
@Override
public void contextDestroyed(ServletContextEvent sce)
【讨论】:
这个修复在 Majorra 2.2.6 上似乎对我不起作用 - 您是否将 FacesContextBootstrap 类放在项目层次结构中的特定位置? 在初始化 servlet 容器的那一刻,faces context 似乎没有被初始化【参考方案4】:我能够通过这种方式修复它:
public static final String BEANS_VALIDATION_AVAILABILITY_CACHE_KEY = "javax.faces.BEANS_VALIDATION_AVAILABLE";
@PostConstruct
private void init()
FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().remove(BEANS_VALIDATION_AVAILABILITY_CACHE_KEY);
FacesContext.getCurrentInstance().getExternalContext().getApplicationMap()
.put(BeanValidator.VALIDATOR_FACTORY_KEY, Validation.buildDefaultValidatorFactory());
【讨论】:
以上是关于Bean 验证不适用于 mojarra 2.2.4的主要内容,如果未能解决你的问题,请参考以下文章
Bean 验证 @Positive 指令不适用于 Integer @PathVariable
JSF 2.2 h:inputFile 不适用于漂亮的面孔[重复]