验证错误后jsf viewparam丢失

Den*_*sGL 8 jsf cdi jsf-2 jboss-weld

我面临以下问题:在一个页面中,我列出了我的应用程序的所有用户,并为每个用户都有一个"编辑"按钮,这是一个"GET"链接?id=<userid>.

编辑页面具有<f:viewParam name="id" value="#{editUserBean.id}"/>元数据.
如果我输入了一些输入错误并提交(我使用CDI Weld Bean验证),页面会再次显示,但我丢失?id=...了URL,因此丢失了我正在编辑的用户的用户ID.

我看过JSF验证错误中描述的类似问题,丢失了值,但是带有inputhidden的解决方案(或更糟糕的是,使用tomahawk,看起来有点过分)需要大量的uggly代码.

我尝试用CDI添加一个"对话",它正在工作,但它看起来对我来说太过分了.

在验证错误的情况下,JSF中是否存在一个简单的解决方案来保留视图参数?

[我的环境:Tomcat7 + MyFaces 2.1.0 + Hibernate Validator 4.2.0 + CDI(Weld)1.1.2]

Arj*_*jms 7

有趣的案例.对于每个人来说,以下最小代码重现了这一点:

的facelet:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
>

    <f:metadata>
        <f:viewParam id="id" name="id" value="#{viewParamBean.id}"/>
    </f:metadata>

    <h:body>

        <h:messages />

        #{viewParamBean.id} <br/>

        <h:form>
            <h:inputText value="#{viewParamBean.text}" >
                <f:validateLength minimum="2"/>
            </h:inputText>

            <h:commandButton value="test" action="#{viewParamBean.actionMethod}"/>
        </h:form>

    </h:body>
</html>
Run Code Online (Sandbox Code Playgroud)

豆:

@ManagedBean
@RequestScoped
public class ViewParamBean {

    private long id;    
    private String text;

    public void actionMethod() {

    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }    
}
Run Code Online (Sandbox Code Playgroud)

如果用viewparam.xhtml?id=12它调用Facelet,它将显示在12屏幕上.如果你输入了一些有效的东西,例如aaaaa,id将从URL中消失,但会一直显示在屏幕上(拥有ui组件的有状态性质).

但是......正如OP所提到的,只要发生任何验证器错误(例如进入a),id就会永久丢失.之后输入有效输入不会带回来.它几乎看起来像一个bug,但我尝试了Mojarra 2.1和Myfaces 2.1,两者都有相同的行为.

更新:

经过一番检查,问题似乎出现在这个'UIViewParameter'(Mojarra)的方法中:

public void encodeAll(FacesContext context) throws IOException {
    if (context == null) {
        throw new NullPointerException();
    }

    // if there is a value expression, update view parameter w/ latest value after render
    // QUESTION is it okay that a null string value may be suppressing the view parameter value?
    // ANSWER: I'm not sure.
    setSubmittedValue(getStringValue(context));
}
Run Code Online (Sandbox Code Playgroud)

然后更具体地说这个方法:

public String getStringValue(FacesContext context) {
    String result = null;
    if (hasValueExpression()) {
        result = getStringValueFromModel(context);
    } else {
        result = (null != rawValue) ? rawValue : (String) getValue();
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

因为hasValueExpression()它是真的,它将尝试从模型(支持bean)获取值.但由于这个bean是请求作用域,因此该请求没有任何值,因为验证刚刚失败,因此没有设置任何值.实际上,有状态值UIViewParameter被覆盖bean作为默认值返回的任何内容覆盖(通常为null,但它当然取决于你的bean).

一个解决方法是创建你的bean @ViewScoped,无论如何这通常都是一个更好的范围(我假设你使用参数从服务中获取用户,并且在每次回发时可能不必一次又一次地执行此操作).

另一种方法是创建自己的版本,UIViewParameter如果验证失败,则不会尝试从模型中获取值(基本上所有其他UIInput组件都会这样做).

  • 仅供参考:修补的`UIViewParameter`可用作OmniFaces的`<o:viewParam>`.另见http://showcase.omnifaces.org/components/viewParam (3认同)