Validation JSF2禁用了仅为第一个周期计算的验证器的属性?

Validation JSF2禁用了仅为第一个周期计算的验证器的属性?,validation,jsf-2,Validation,Jsf 2,我发现我在JSF2中使用的任何验证器的disabled属性只有在我的托管bean是viewscope的情况下才会在第一个周期中进行计算 但我想根据我从第四个更新阶段获得的数据,为我的验证器使用disabled属性。因此,我希望在同一视图上执行的所有循环中对其进行重新评估 xhtml页面示例: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtm

我发现我在JSF2中使用的任何验证器的disabled属性只有在我的托管bean是viewscope的情况下才会在第一个周期中进行计算

但我想根据我从第四个更新阶段获得的数据,为我的验证器使用disabled属性。因此,我希望在同一视图上执行的所有循环中对其进行重新评估

xhtml页面示例:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:head></h:head>
<h:body>
    <h:form>
        <h:panelGrid id="pnlGrid">          
            <h:inputText id="someValueId" value="#{testPageBean.someValue}">                
                <f:validateLength minimum="2" maximum="4" 
                   disabled="#{testPageBean.disableValidateLength}"/>
            </h:inputText>
            <h:messages for="someValueId"/>

            <h:commandButton action="#{testPageBean.doSomething}" 
               value="Do something" />
        </h:panelGrid>
    </h:form>
</h:body>
</html>
我知道我应该责怪实现com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl:

这三行导致验证程序在执行操作时未重新评估其禁用属性:-(

请给我一个提示,是什么促使JSF2的人以这种方式实现,或者更好地解决我的问题

编辑:

JSF2版本:2.0.3-SNAPSHOT

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>JSF2Testing</display-name>
    <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>/faces/*</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
        <param-value>false</param-value>
    </context-param>

</web-app>
我对该解决方案的注意事项:

  • 即使对于标准验证器,也需要自己的实现
  • 取决于组件(inputText)级别的属性
  • 即使不应该触发验证程序,也会触发验证程序
  • 我非常确定,当为验证器提供客户端验证时,它的行为将不会像我们预期的那样
  • 我认为非常丑陋,不遵循JSF2:-()
您已经成为鸡蛋问题的另一个受害者,部分状态保存和查看范围的bean,如即将发布的Mojarra 2.2中所述

当您看到视图作用域bean的构造函数在每个请求上被调用时,而不是在视图的第一个请求上被调用一次时,您还应该立即意识到有些事情并不完全正确

修复此问题的方法之一是完全禁用部分状态保存:

<context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>false</param-value>
</context-param>

javax.faces.PARTIAL_STATE_保存
错误的
另见:

谢谢您的回答。我按照您的描述明确地设置了部分状态保存。但是禁用的属性仍然没有被重新评估。托管bean的构造函数第一次只被调用一次。在执行操作后,构造函数没有被调用,并且所有6个阶段都被通过,但是方法isDisableValidateLength没有被调用。嗯,y你是对的。该方法不会在后续请求中调用。在创建视图期间只调用一次。我在Mojarra 2.1.4和MyFaces 2.1.3中都看到了这种行为。我建议按照我在第二个“请参阅”链接中的回答中所述的方法进行处理。嗨,BalusC,我浏览了你的链接,并尝试实现一些解决方案(请参阅Edit2)。我不知道我是否理解你的建议。但无论如何,我不喜欢我提出的解决方案。因此,如果你知道如何以更清晰的方式解决问题,我将不胜感激。我会将此报告给JSF人员。@BalusC Hi,这很奇怪,因为我在禁用的情况下会出现这种行为,但在渲染的情况下不会出现这种行为。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>JSF2Testing</display-name>
    <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>/faces/*</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
        <param-value>false</param-value>
    </context-param>

</web-app>
<h:inputText id="someValueId" value="#{testPageBean.someValue}">                
    <f:validator validatorId="myLengthValidator"/>
    <f:attribute name="disableMyLengthValidator" value="#{testPageBean.disableValidateLength}"/>
    <f:attribute name="minimum" value="2" />
    <f:attribute name="maximum" value="4" />
</h:inputText>
import java.io.Serializable;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.LengthValidator;
import javax.faces.validator.ValidatorException;

@FacesValidator("myLengthValidator")
public class MyLengthValidator extends LengthValidator implements Serializable {

    public MyLengthValidator() {
        System.out.println("MyLengthValidator constructor");
    }

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {     
        if((Boolean)component.getAttributes().get("disableMyLengthValidator")) {
            return;
        }       
        setMinimum(Integer.valueOf((String)component.getAttributes().get("minimum")));
        setMaximum(Integer.valueOf((String)component.getAttributes().get("maximum")));
        super.validate(context, component, value);
    }
}
<context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>false</param-value>
</context-param>