在viewParam上转换GET请求参数时出现问题

时间:2013-06-26 00:59:31

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

我正在尝试转换从另一个视图传递的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>

支持bean

@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();
    }
}

1 个答案:

答案 0 :(得分: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> 

这似乎是reported issue with JSF 2.2

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

<强>更新 好像有些taglib没有完全正常运行或者我读错了吗?

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