调用第二个ajax请求时,带有Converter和ViewScoped异常的f:viewParam [英] f:viewParam with Converter and ViewScoped exception out when invoke the second ajax request

查看:118
本文介绍了调用第二个ajax请求时,带有Converter和ViewScoped异常的f:viewParam的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个f:viewParam,我尝试绑定验证并将userId转换为Player,但得到了意外的结果.

I have this f:viewParam that I try to bind validate and convert a userId into Player, and I got an unexpected results.

<f:metadata>
    <f:viewParam name="userId" value="#{myBean.selectedPlayer}" converter="pConverter"
         converterMessage="Bad Request. Unknown User" required="true"
         requiredMessage="Bad Request. Please use a link from within the system" />

</f:metadata>
<h:body>
    <p:messages id="msgs"/>        
    <h:form>
        <ul>
            <li><a href="index2.xhtml?userId=1">Harry</a></li>
            <li><a href="index2.xhtml?userId=2">Tom</a></li>
            <li><a href="index2.xhtml?userId=3">Peter</a></li>
        </ul>            
    </h:form>
    <h:form>
        <h:panelGrid columns="2" rendered="#{not empty myBean.selectedPlayer}">

            <h:outputText value="Id: #{myBean.selectedPlayer.id}"/>

            <h:outputText value="Name: #{myBean.selectedPlayer.name}"/>

        </h:panelGrid>
    </h:form>
    <h:form id="testForm">
        <h:inputText value="#{myBean.text}"/>
        <p:commandButton value="Switch" update=":msgs testForm"/>
        <h:outputText value="#{myBean.text}" rendered="#{not empty myBean.text}"/>
    </h:form>    
</h:body>

我的转换器看起来像这样

My Converter look like this

@FacesConverter(value="pConverter")
public class PConverter implements Converter {
private static final List<Player> playerList;
static{
    playerList = new ArrayList<Player>();        
    playerList.add(new Player(1, "Harry"));
    playerList.add(new Player(2, "Tom"));
    playerList.add(new Player(3, "Peter"));
}

@Override
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
    if(value == null || !value.matches("\\d+")){
        return null;
    }
    long id = Long.parseLong(value);
    for(Player p : playerList){
        if(p.getId() == id){
            return p;
        }
    }
    throw new ConverterException(new FacesMessage("Unknown userId: " + value));

}

@Override
public String getAsString(FacesContext fc, UIComponent uic, Object value) {
    if(!(value instanceof Player) || value == null){
        return null;
    }
    return String.valueOf(((Player)value).getId());
}
}

当我单击三个链接(Harry,Tom,Peter)时,转换器运行良好.它转换id并将player绑定回我的托管bean.然后,我在文本框中键入内容,然后单击Switch,它第一次正常运行时,我键入的内容将出现在按钮旁边,但随后我更改了键入的内容,然后再次单击Switch,然后出现错误消息Bad Request. Please use a link from within the system,这是f:viewParamrequired错误消息.如果我将f:viewParam取出,那么一切正常.出人意料的是,如果我从f:viewParam切换到o:viewParam(OmniFaces),则效果很好.

As I click the three link (Harry, Tom, Peter), the converter work great. It converter the id and bind the player back to my managed bean. I then type something in the text box, then click Switch, the first time it work fine, what I typed appear next to the button, but then I change what I type, and click Switch again, then error message appear Bad Request. Please use a link from within the system, which is the error message for required for f:viewParam. If I took the f:viewParam out then everything work fine. Surprisingly, if I switch from f:viewParam to o:viewParam (OmniFaces), then it work great.

推荐答案

这是因为<f:viewParam>可以在每个HTTP请求上运行,也可以在回发上运行.对于普通的GET链接,它在您的情况下很好用,因为您正在链接中准确传递该参数.对于POST表单,此操作将失败,因为您没有在按钮中传递该参数.因此,它在请求参数映射中变为null,并且required验证程序启动,因此出现此验证错误.

That's because the <f:viewParam> runs on every single HTTP request, also on postbacks. It works in your case fine for plain GET links, because you're passing exactly that parameter in the links. It fails in your case for POST forms, because you aren't passing that parameter in the button. So it becomes null in the request parameter map and the required validator kicks in and hence this validation error.

要使<f:viewParam required="true">在POST表单上也保持满意,基本上,您需要在命令按钮/链接中通过<f:param>保留初始请求参数.

To keep the <f:viewParam required="true"> happy on POST forms as well, you basically need to retain the initial request parameter by <f:param> in the command buttons/links.

<p:commandButton value="Switch" update=":msgs testForm">
    <f:param name="userId" value="#{param.userId}" />
</p:commandButton>

OmniFaces <o:viewParam> ,旨在与View范围内的bean结合使用,在isRequired() getter(

The OmniFaces <o:viewParam>, which is designed to be used in combination with view scoped beans, has an additional check in the isRequired() getter (source code here):

@Override
public boolean isRequired() {
    // The request parameter get lost on postbacks, however it's already present in the view scoped bean.
    // So we can safely skip the required validation on postbacks.
    return !FacesContext.getCurrentInstance().isPostback() && super.isRequired();
}

因此,这会在每个回发中跳过required验证器(此外,由于其无状态性质,它还会跳过在每个回发中设置模型值).这就是为什么您看不到验证错误并且仍然具有正确的模型值(不会在每次回发时重置)的原因.

So, this skips the required validator on every postback (and additionally, it also skips setting the model value on every postback due to its stateless nature). That's why you don't see the validation error and you still have the proper model value (which isn't reset on every postback).

这篇关于调用第二个ajax请求时,带有Converter和ViewScoped异常的f:viewParam的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆