0 Replies Latest reply on Nov 27, 2006 6:01 AM by pbakker

    Lazy loading behaviour

    pbakker

      I'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.