Атрибут JSF2 отключен для валидатора, оцененного только для первого цикла? - PullRequest
1 голос
/ 13 января 2012

Я обнаружил, что отключенный атрибут для любого валидатора, который я использую в JSF2, оценивается только в первом цикле, если мой управляемый компонент - ViewScoped.

Но я хотел бы использовать disabled атрибут для моих валидаторов на основе данных, которые я получаю с 4-го этапа обновления.Поэтому я ожидаю, что он будет переоценен во всех циклах, выполняемых в одном и том же представлении.

Пример страницы 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>

и ее область видимости управляемый компонент

package cz.kamosh;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class TestPageBean implements Serializable {

    boolean disableValidateLength = false;

    private String someValue;

    public TestPageBean() {
        System.out.println("Constructor TestPageBean");
    }

    public String getSomeValue() {
        return someValue;
    }

    public void setSomeValue(String someValue) {
        this.someValue = someValue;
    }

    /**
     *  Some action without any navigation as a result
     */
    public void doSomething() {
        disableValidateLength = !disableValidateLength;
        System.out.printf(
                "DoSomething, someValue: %1$s, disableValidateLength: %2$b\n",
                someValue, disableValidateLength);
    }

    public boolean isDisableValidateLength() {
        System.out.printf("IsValidateLength, disableValidateLength: %1$b\n", 
                disableValidateLength);
        return disableValidateLength;
    }
}

Я знаю, что должен винить реализацию com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl :

private void applyNested(FaceletContext ctx,
                             UIComponent parent) {

        // only process if it's been created
        if (!ComponentHandler.isNew(parent)) {
            return;
        }
    ...
}

Эти три строки приводят к тому, что валидатор не переоценивает свои отключен атрибут при выполнении действия: - (

Не могли бы вы дать мне подсказку, что побудило ребят из 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>


EDIT2 Попытка следовать предложению BalusC

Измененияна странице:

<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);
    }
}

Мои заметки об этом решении:

  • RequirЭто собственная реализация, даже если для стандартных валидаторов
  • зависит от атрибутов на уровне компонента (inputText)
  • валидатор запускается, даже если он не должен быть
  • Я уверен, что этоне будет вести себя так, как мы ожидаем, когда для валидатора предоставляется проверка на стороне клиента
  • Я считаю, что это очень уродливо и не соответствует JSF2: - (

1 Ответ

0 голосов
/ 13 января 2012

Вы стали еще одной жертвой проблемы куриного яйца с частичным сохранением состояния и просмотром бобов в области видимости, как описано в выпуске 1492 , который должен быть исправлен в готовящейся Mojarra 2.2.

Вы также должны были сразу же понять, что что-то не совсем правильно, когда вы видели конструктор bean-объекта области видимости, вызываемый на каждый запрос вместо одного раза при первом запросе представления.

Один из способов исправить это вообще отключить частичное сохранение состояния:

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

Смотри также:

...