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.