1

我正在尝试转换从另一个视图传递的 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 博客文章,并且,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();
    }
}
4

1 回答 1

3

在查看您发送的实际代码后,我能够找到问题所在。问题不在于转换器。它与项目顶部的 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> 

这似乎是JSF 2.2 的一个报告问题

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

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

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

于 2013-06-27T02:51:07.390 回答