How do I efficiently update a property contained in several classes?

46 views Asked by At

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

So, how can I efficiently distribute the change information from one bean to others that contain (now stale) copies of the edited entity?

1

There are 1 answers

0
mabi On BEST ANSWER

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 to ContactMgr 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.