Lazy loading behaviour
pbakker Nov 27, 2006 6:01 AMI'm working on a demo-app and walked into some lazy-loading related issues.
I did find a solution, but I would like to find out why the other things I tried didn't work, so I can get a better understanding of things.
The situation is as follows:
There is a search page, that lists customers.
Every customer holds a list of messages, which should be lazily loaded.
The messages are not shown on the search page.
When clicked on a row, an edit screen is shown, which does show the customer's messages.
I use the SeamExtendedManagedPersistencePhaseListener and have a ManagedPersistenceContext configured.
The following code was my first trial, which gives a LazyInitializationException when opening the edit page.
FindCustomerBean
@Stateful
@Name("findCustomer")
@Scope(ScopeType.SESSION)
public class FindCustomersBean implements FindCustomer{
@DataModel("customers")
private List<Customer> customers;
@DataModelSelection @Out(required=false)
private Customer customer;
@Logger
private Log log;
@In(create=true)
private EntityManager seamEntityManager;
public String edit() {
log.debug("Editing customer '" + customer.getName() + "'");
return "edit";
}
@Factory("customers")
public void initializeCustomers() {
customers = seamEntityManager.createQuery("select c FROM Customer c").getResultList();
}
@Destroy @Remove
public void destoy() {
}
}
EditCustomerBean
@Stateful
@Name("editCustomer")
@Scope(ScopeType.CONVERSATION)
public class EditCustomerBean implements EditCustomer {
private FindCustomer findCustomer;
@In private Customer customer;
private String newMessage;
@Logger private Log log;
@In private EntityManager seamEntityManager;
@Create @Begin
public void create() {
log.debug("Starting customer edit conversation");
}
public Customer getCustomer() {
return customer;
}
@End
public String save() {
return "saved";
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public String addMessage() {
Message message = new Message();
message.setMessage(newMessage);
message.setDate(new Date());
message.setFromTo("To");
customer.getMessages().add(message);
newMessage = new String();
return "addedMessage";
}
public String getNewMessage() {
return newMessage;
}
public void setNewMessage(String newMessage) {
this.newMessage = newMessage;
}
@Remove @Destroy
public void destroy() {
log.debug("Destroying customer edit");
}
}
In the editCustomer.xhtml Facelets page, the list of messsages is displayed in a datatable with value="#{editCustomer.customer.message}".
This doesn't work. From what I understand from the documentation, this is because I started a new conversation. Is this really the reason, or is something else happening?
The next thing I tried is to add the following line to the @Create method of EditCustomerBean:
customer = seamEntityManager.merge(customer);
This should re-attach the customer to the session.
The create method is executed without errors, but it didn't solve the problemm.
Now my final solution that did work. I do not understand why this is any different from the example above.
public Customer getCustomer() {
customer = seamEntityManager.merge(customer);
return customer;
}
I simply moved the same line of code to the getCustomer method.
The only difference I can think of, is that the getCustomer method is called at a later time.