【问题标题】:Issue when converting GET request parameters on viewParam在 viewParam 上转换 GET 请求参数时出现问题
【发布时间】:2013-06-26 00:59:30
【问题描述】:

我正在尝试转换从另一个视图传递的 GET 请求参数,如下所示:

<f:metadata>
    <f:viewParam name="id" 
                 value="#{targetViewBean.fooFromSourceView}" 
                 converter="fooConverter" 
                 converterMessage="Foo converter message"
                 required="true" requiredMessage="Foo required message"/>
    <f:viewAction action="#{targetViewBean.doSomethingWithFoo()}"/>
</f:metadata>

但是只有Converter.getAsString(..., Object value)方法被调用并且value总是为空,即使你真的发送了GET参数。

我找到了BalusC blog post about this,并且,AFAIK,我一直遵循它。还是不行。完整代码如下:

源视图

<h:head>
    <title>Source view</title>
</h:head>
<h:body>
    <ul>
        <ui:repeat value="#{sourceViewBean.foos}" var="foo">
            <li>
                <h:link value="Foo \##{foo.id}" outcome="target-view">
                    <f:param name="id" value="#{foo.id}" />
                </h:link>
            </li>
        </ui:repeat>
    </ul>
</h:body>

支持豆

@Named @ViewScoped
public class SourceViewBean implements Serializable {

    public Collection<Foo> getFoos() {
        return Db.INSTANCE.getFoos();
    }

    private static final long serialVersionUID = 1L;
}

目标视图

<f:metadata>
    <f:viewParam name="id" 
                 value="#{targetViewBean.fooFromSourceView}" 
                 converter="fooConverter" 
                 converterMessage="Foo converter message"
                 required="true" requiredMessage="Foo required message"/>
    <f:viewAction action="#{targetViewBean.doSomethingWithFoo()}"/>
</f:metadata>
<h:head>
    <title>Target view</title>
</h:head>
<h:body>
    <h:outputText value="ID: #{targetViewBean.fooFromSourceView.id}" />
</h:body>

目标视图支持 bean

@Named 
@ViewScoped
public class TargetViewBean implements Serializable {
    private Foo fooFromSourceView;

    public void doSomethingWithFoo() {
        System.out.println("Foo is here? " + fooFromSourceView != null);
    }

    public Foo getFooFromSourceView() {
        return fooFromSourceView;
    }

    public void setFooFromSourceView(Foo fooFromSourceView) {
        this.fooFromSourceView = fooFromSourceView;
    }

    private static final long serialVersionUID = 1L;
}

转换器

@FacesConverter(value = "fooConverter")
public class FooConverter implements Converter {
    @Override
    public Object getAsObject(
            FacesContext context, UIComponent component, String value) {
        if (value == null || !value.matches("\\d+")) {
            return null;
        }

        for (Foo foo : Db.INSTANCE.getFoos()) {
            if (foo.getId().equals(Integer.parseInt(value))) {
                return foo;
            }
        }
        throw new ConverterException(new FacesMessage("No Foo found!"));
    }

    @Override
    public String getAsString(
            FacesContext context, UIComponent component, Object value) {
        if (!(value instanceof Foo) || ((Foo) value).getId() == null) {
            return null;
        }

        return ((Foo) value).getId().toString();
    }
}

【问题讨论】:

  • 如果值为 null ,你怎么知道参数正在被发送?我尝试运行示例代码,它对我来说运行良好。唯一的区别是我将Db.INSTANCE.getFoos(); 更改为List&lt;Foo&gt;,而doSomethingWithFoo() 正在输出true。你确定它不在其他地方吗?
  • GET 请求包含具有适当值的id 参数。由于getAsString value 为空,doSomethingWithFoo() 永远不会被调用。可能是别的东西,但我不知道是什么。代码来自 NetBeans 7.3.1 中一个全新的 Java EE 7 maven 企业应用程序项目。
  • 嗯...我假设outputText 只是显示ID
  • 好的,让我仔细检查一下我的工作。
  • 我刚刚在转换器端进行了检查,id 请求参数确实存在。顺便说一句,在启动 glassfish 时会抛出 2 条消息,但我认为它与 Class 'javax.ejb.PostActivate' not found, interception based on it is not enabled 无关,而 javax.ejb.PrePassivate 的消息相同。

标签: jsf viewparams jsf-2.2 java-ee-7


【解决方案1】:

在查看了您发送的实际代码后,我能够找到问题所在。问题不在于转换器。它与项目顶部的 xml 命名空间一起使用。例如,在 source-view.xml 你有

 xmlns:h="http://xmlns.jcp.org/jsf/html"
 xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
 xmlns:f="http://xmlns.jcp.org/jsf/core"

但他们应该是

xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">

target-view.xhtml应该是

xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">

GlassFish 似乎出于某种原因更改了命名空间。我并没有试图找出它为什么会这样,所以请记住这一点。无论如何,一旦我更改了它,正确的相位就会在 GlassFish 的输出窗口中输出。因此,在需要的地方进行必要的更改。

注意:如果您想知道为什么会出现以下错误

The metadata component needs to be nested within a f:metadata tag. Suggestion: enclose the necessary components within <f:metadata> 

这似乎是reported issue with JSF 2.2

另外,我不确定为什么您的 h:link 嵌套在 h:form 中。这不是必需的。

更新 似乎有些标签库功能不全,还是我读错了?

https://java.net/jira/browse/JAVASERVERFACES-2868

【讨论】:

  • 是的,我在 glassfish 4 上使用 Java EE 7(我提到过吗?如果没有,非常抱歉)
  • 你做到了,哈哈。不用担心。直到今天早上才点击。
  • 我猜这是 glassfish 的一些问题,因为这些是新的命名空间。嵌套是其中之一,将所有东西都扔到墙上,看看有什么粘着的瞬间。感谢您在这方面走了这么远:)
  • 不客气。刚升级的时候不知道有新的。现在我觉得我的答案是缺乏的。我会调查的。
  • AFAIK xmlns.jcp.org 是 JSF-2.2 的正确命名空间。如果它们包含错误,那就另当别论了。
猜你喜欢
  • 2012-10-02
  • 1970-01-01
  • 2014-07-06
  • 2022-01-16
  • 2021-09-06
  • 1970-01-01
  • 1970-01-01
  • 2019-09-08
  • 1970-01-01
相关资源
最近更新 更多