tags:

views:

129

answers:

2

I am trying to populate the list of an <h:selectOneMenu>. However, the list that I am trying to retrieve is part of another class that is a variable in the base class.

Here is what I have and I'm not sure if this is even possible or how to do it.

I have a Citation class with the following:

public class Citation {
    private int id;
    private String title;
    private Status status;

    // getters and setters
}

Then I have a Status class with the following:

public class Status {
    private int id;
    private String name;

    public List<Status> getAll() {
        // goes to the database and gets a list of status objects
        System.out.println("I was called!");
    }

    // getters and setters
}

Then on my xhtml page, I have the following:

<h:selectOneMenu id="citation_status" value="#{citation.status}">
    <f:selectItems value="#{citation.status.all}" var="s"
            itemLabel="#{s.name}" itemValue="#{s.id}" />
</h:selectOneMenu>

However, this doesn't seem to be calling the getAll method in the Status class at all. When the page finishes loading, the select box is empty and the console does not have the output of I was called! from the getAll() method.

I'm a bit new to JSF and I've tried searching the best that I can, but I'm not really sure the terminology to use when searching for this because it's not technically called a "subclass", but that's the best name I can come up with, so needless to say, I've come up with nothing from searching.

Additional Information

If it helps:

  • I'm using Glassfish as my application server
  • I'm using Hibernate for my ORM
  • I'm using JSF 2.0
+2  A: 

Apparently #{citation.status} returned null.

That said, this isn't going to work. The h:selectOneMenu value must match the same type as f:selectItem itemValue which is in this case an int. You would get a converter exception.

How to solve this the best depends on the functional requirement which is yet unclear in the question. Maybe you need f:selectItem itemValue="#{s}", or you need h:selectOneMenu value="#{citation.id}".


Update: as to the converter, here's a kickoff example:

@FacesConverter(forClass=Status.class)
public class URLConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        try {
            return someStatusDAO.findById(Long.valueOf(value));
        } catch (SomeException e) {
            throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Status", value)), e);
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return String.valueOf(((Status) value).getId());
    }

}
BalusC
Now that I think about it, that would make sense because `status` has not been initialized. For the `<f:selectItems>` value attribute, could I use `status.all` rather than `citation.status.all`?
Jared
If there's a `#{status}` somewhere in the scope, then certainly yes. You yet have to fix the potential conversion problem :)
BalusC
That works for at least getting the items in the list. As for the conversion problem, is there a way to set the value to an actual object? I tried using `<f:selectItem itemValue=#{s}">`, but got the error `Error setting value Status for null Converter`. I'm assuming that I need to look into using a Converter to handle this?
Jared
Right! :) Create a `@FacesConverter(forClass=Status.class)` which `implements javax.faces.converter.Converter`. Implement the two methods `getAsString()` (just let it return `id` as `String` or so) and `getAsObject()` (let it return "real" `Status` by obtained `id`) accordingly.
BalusC
That works perfectly. Thank you so much for your help!
Jared
You're welcome.
BalusC
A: 

You need a public getter for status in Citation.

Thorbjørn Ravn Andersen