views:

99

answers:

2

I have a many-to-many relationship between the two entities called events and artists, both are annotated to be lazy loaded. When I load an artist, I initialize its events because the session will be closed afterwards using

Hibernate.initialize(artist.getEvents());

A test in pure Java works fine and I can access the events and its properties afterwards.

But in the .xhtml page presenting the result, I can only access the artist's properties and test if there are any events available, Artist is the backing bean, getData() returns the Artist, the following line still works:

<h:outputText value="No events available" rendered="#{empty artist.data.events}"/>

But when I want to access the properties of the events in a dataTable using

<h:dataTable value="#{artist.data.events}" var="event" rendered="#{not empty artist.data.events}">
  <h:column>
    <h:outputText value="#{event.title}"/>
  </h:column>
</h:dataTable>

I get the followig exception:

/artist.xhtml @48,63 value="#{event.title}": The class 'org.hibernate.collection.PersistentSet' does not have the property 'title'.

My first thought was that Hibernate's initialize method does not work together with JSF2, but event when I change the FetchType from LAZY to EAGER I end up getting the same result.

The Event class looks like this, for brevity I only included the parts relevant to the title property:

@Entity()
@Table(name="Events")
@SequenceGenerator(name="events_id", sequenceName="event_seq", initialValue=1, allocationSize=1)
public class EventData implements Serializable {

    private String title;
    // other private variables

    public EventData() {}

    public EventData(String title, ...) {
        this.title = title;
        // ...
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    // other setters/getters, equals/getHashCode overrides    

}
A: 

Voodoo is required to expose any bean to the #{...} facility. The simplest is to use CDI if your web container supports it, but otherwise look at the @ManagedBean annotation in JSF2.

Thorbjørn Ravn Andersen
I have other xhtml pages accessing the Artist's properties just fine which is a @ManagedBean
hro
+2  A: 

UIData components can only iterate over an T[], List<T> or a DataModel<T>, not over a Set<T> because there's no way to identify an element in a Set<T> by an index, while it is required in UIData components.

@Bozho has written a weblog describing one way how to go around it. Other ways are to configure JPA to use List<T> instead or to add a getter which wraps it in a List<T> or DataModel<T> and use it instead in UIData component. E.g.

public DataModel<Event> getEventModel() {
    return new ArrayDataModel<Event>(events.toArray(new Event[events.size()]));
}

This by the way uses the same instances (doesn't copy/clone/recreate them), so all changes will be reflected in the right instances.

BalusC
thanks for the exact answer BalusC, after I added a property events (List<EventData> getEvents()) to my Artist backing Bean it worked!
hro