【问题标题】:f:viewParam with Converter and ViewScoped exception out when invoke the second ajax requestf:viewParam 在调用第二个 ajax 请求时出现 Converter 和 ViewScoped 异常
【发布时间】:2012-05-18 13:53:26
【问题描述】:

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

<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>

我的转换器看起来像这样

@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,这是required 的错误消息f:viewParam。如果我把 f:viewParam 拿出来,那么一切正常。令人惊讶的是,如果我从 f:viewParam 切换到 o:viewParam (OmniFaces),那么效果很好。

【问题讨论】:

    标签: java validation jsf viewparams omnifaces


    【解决方案1】:

    那是因为&lt;f:viewParam&gt; 在每个 HTTP 请求上运行,在回发时也是如此。它在您的情况下适用于普通的 GET 链接,因为您在链接中准确地传递了该参数。对于 POST 表单,它会失败,因为您没有在按钮中传递该参数。因此它在请求参数映射中变为null,并且required 验证器启动,因此出现此验证错误。

    为了让&lt;f:viewParam required="true"&gt; 也能在 POST 表单上满意,您基本上需要在命令按钮/链接中保留 &lt;f:param&gt; 的初始请求参数。

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

    OmniFaces &lt;o:viewParam&gt;,旨在与视图范围的 bean 结合使用,在 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 验证器(此外,由于其无状态特性,它还会在每次回发时跳过设置模型值)。这就是为什么您看不到验证错误并且您仍然拥有正确的模型值(不会在每次回发时重置)。

    【讨论】:

    • 非常感谢。 Omnifaces 非常棒,BalusC。我有一个关于o:viewParam 的问题,在您的博客中,您说omnifaces 将避免在每次ajax 请求调用时调用Converter,但是,它似乎总是进入方法getAsString()。所以我想知道这种行为是否正确。我知道getAsObject 是设置模型值的原因,所以不调用getAsObject 是一个很大的改进。我对此表示感谢。
    • getAsString() 将在对象需要转换为字符串时被调用(以呈现在生成的 HTML 中)。但它应该是一个相当便宜的工作,因为它应该是它的一个属性的字符串值。那时您已经拥有该对象,因此不需要昂贵的数据库工作。
    猜你喜欢
    • 2015-07-09
    • 2012-11-01
    • 2011-07-14
    • 1970-01-01
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    相关资源
    最近更新 更多