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
}
UIData
components can only iterate over an T[]
, List<E>
or a DataModel<E>
, not over a Set<E>
because there's no way to identify an element in a Set<E>
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<E>
instead or to add a getter which wraps it in a List<E>
or DataModel<E>
and use it instead in UIData
component. Eg
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.
Update : in the upcoming JSF 2.2, the UIData
will finally support Collection<E>
, which thus includes Set<E>
. Another way is to create a custom EL resolver as answered here: How do I use a java.util.Set with UIData in JSF. Specifically h:datatable?
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.