I've this simple pattern where a controller/backing bean manages a single entity instance in a @ViewScoped
context. The view takes a couple of those backing beans and displays the information. The approach I'm using has been described by Andy Gibson in this blog post.
Now I need to display information about two entities, a Person and it's Contacts:
@Entity
public class Person {
@Id @Generated
private Long id;
@OneToMany(mappedBy = "owner")
private Set<Contact> contacts = new LinkedHashSet<>();
}
@Entity
public class Contact {
@Id @Generated
private Long id;
private String content;
@ManyToOne
private Person owner;
@OneToMany
private Set<File> attachments;
}
There's a ContactMgr and a PersonMgr, and I start by fully loading the Person
via a f:viewAction
. I then display a list of the person's contacts and let the user edit them in a rich:popupPanel
:
<h:dataTable value="#{personMgr.instance.contacts}" var="c">
<h:column><a4j:commandLink value="#{c.content}"
actionListener="#{contactMgr.setId(c.id)}"
action="#{contactMgr.fullInit()}"
render=":contactInnards"
oncomplete="#{rich:component('contactPanel')}.show();" />
</h:column>
</h:dataTable>
Clicking the link loads the selected contact and lets the user edit as she likes. The user then clicks "save" and the changes get persisted. Up to here, everything's fine.
But now I want to re-render the contact list. How do I make PersonMgr
aware of the changed contact? The list of contacts was populated some time ago and not changed in ContactMgr
.
I've looked at three solutions already:
- directly setting the contact on
ContactMgr
, but I really need to initialize a few more fields before the popup gets displayed as I don't want to incur that cost for every contact. - A complete site reload is a possibility, but also quite costly.
- With
@Observe
I'm afraid I need a dozen methods, one for each list I attach toPerson
So, how can I efficiently distribute the change information from one bean to others that contain (now stale) copies of the edited entity?
I've come to think that the problem is effectively like cache invalidation - a known hard problem. I could probably cook something up to expand on the
@Observe(notifyOberserver = IF_EXISTS)
idea and make it work without drowning in new methods.But I've found that simply moving the task of backing the
dataTable
toContactMgr
and having all the logic of populating, selecting from and updating the list reside in a single class has worked wonders to avoid the issue altogether.