1

I'm trying to convert GET request parameters passed from another view like this:

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

But only the Converter.getAsString(..., Object value) method is called and value is always null, even thou the GET parameter is really sent.

I found BalusC blog post about this and, AFAIK, I followed it to the letter. Still no good. Here's the full code:

Source view

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

Backing bean

@Named @ViewScoped
public class SourceViewBean implements Serializable {

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

    private static final long serialVersionUID = 1L;
}

Target view

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

Target view backing 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;
}

The converter

@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();
    }
}
NoElles
  • 13
  • 3
  • How can you tell that parameters are being sent if value is null ? I tried running a sample code and it was working fine for me. The only difference is that I changed `Db.INSTANCE.getFoos();` to `List` and `doSomethingWithFoo()` was outputting `true`. Are you sure it's not somewhere else ? – Andy Jun 26 '13 at 21:27
  • The GET request contains the `id` parameter with a proper value. And since `getAsString` `value` is null, the `doSomethingWithFoo()` never gets called. It could be something else, but I have no idea what. The code is from a brand new Java EE 7 maven enterprise application project in NetBeans 7.3.1. – NoElles Jun 26 '13 at 21:37
  • Hmmm...and I'm assuming the `outputText` simply displays `ID` – Andy Jun 26 '13 at 22:17
  • Ok let me double check my work. – Andy Jun 26 '13 at 22:19
  • I've just checked on the converter side and the `id` request parameter is really there. Btw, on startup glassfish throws 2 messages, but I think it's unrelated `Class 'javax.ejb.PostActivate' not found, interception based on it is not enabled` and the same message for `javax.ejb.PrePassivate`. – NoElles Jun 26 '13 at 22:52
  • Oh, and it's just a maven web application. – NoElles Jun 26 '13 at 22:53

1 Answers1

3

I was able to find the problem after taking a look at the actual code you sent. The issue is not with the converter. It's with the xml namespaces at the top of your project. For instance, in source-view.xml you have

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

But they should be

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

And target-view.xhtml should be

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

GlassFish seems to change the namespaces for some reason. I didn't try to find out why it behaves like that though so keep that in mind. Anyway, once I changed it, the correct phases were being outputted in GlassFish's output window. So go and make the necessary change where needed.

Note: In case you are wondering why you are getting the following error

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

This seems to be a reported issue with JSF 2.2

Also, I'm not sure why your h:link is nested inside an h:form. It's not needed.

UPDATE Seems like some of the taglibs are not fully functional or am I reading this wrong ?

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

Andy
  • 5,900
  • 2
  • 20
  • 29
  • Yes, I'm using Java EE 7 on glassfish 4 (have I mentioned that? If no, big sorry) – NoElles Jun 27 '13 at 19:23
  • You did lol. No worries. It just never clicked until this morning. – Andy Jun 27 '13 at 19:27
  • I guess this is some issue with glassfish since those are the new namespaces. The nesting was one of those throw everything at the wall and see what sticks moments. Thanks for going that far on this :) – NoElles Jun 27 '13 at 23:56
  • You are welcome. I didn't know there were new ones since I just upgraded. Now I feel my answer is lacking. I'll investigate. – Andy Jun 28 '13 at 00:05
  • AFAIK `xmlns.jcp.org` are the correct namespaces for JSF-2.2. If they contain bugs, that is a different story. – Ioannis Deligiannis Jul 10 '13 at 09:12
  • @johnd they do. I didn't mean that they're not from this answer. It was my first time using JSF 2.2 and I didn't know about them at first. Should I reword this ? – Andy Jul 10 '13 at 13:39