4 Replies Latest reply on Jun 11, 2009 2:37 PM by coresystems_rit

    Lazy Load Execption with Seam managed persistence context, not so with container managed pc

    coresystems_rit

      Hi


      I've experience a somehow strange situation with two beans and a lazy load exception when using seam managed persistence context.


      Starting Situation:
      - (bean1) SFSB with scope SESSION and a collection annotated as a data model (@DataModel). Additionally there is a method which loads the data from the database into the collection. This method is also marked with @Factory as well as @Observer(some.event).
      - (bean2) SFSB with scope CONVERSATION. In one of those method the some.event gets fired.


      The bean1 contains a list of event entities (e.g. party events or so). One has the possibility to edit such an event. In this case, a method on bean2 gets called. This method is annotated with @Begin. After doing the modifications on the event, the users clicks the save button. This button calls the commit() method on the bean2 (bean2.commit()) which is annotated with @End(beforeRedirect eq true). If the modifications could be done, the bean2 fires an event some.event. This event is observed by bean1 with @Observer(some.event). In the method with the @Observer annotation, the bean1 updates the collection behind the data model to reflect the changes done during the previous conversation (related to bean2).


      Problem:
      If I am using a seam managed persistence context I am getting a lazy loading exception. As far as I understand, the situation of the method calls is as follow:
      1) user clicks save - bean2.commit();



      2) bean2.commit(): Events.instance.raiseEvent(some.event)
      3) directly after the event all observers get notified (before the commit method finishes) - bean1.observeMethod catches
      4) bean1.observeMethod reloads data from the database
      5) bean1.observeMethod is done, jumps now back to bean2.commit
      6) bean2.commit finishes the remaining code
      7) jsf starts rerendering user interface (- access the collection)


      As the entity manager used in step 4 to load the data from the database isn't available any more in step 7 (because it belonged to bean2. but the conversation in bean2 already ended and therefor the pc is destroyed), i get a lazy loading exception. If I change from @In (or better say from seam managed persistence context to a container managed one (@PersistenceContext(type eq EXTENDED)), i didn't get such a lazy load exception. Unfortunately the container managed persistence context doesn't reload the data from the database).


      My question is, how can I stick a seam managed persistence context to a session? And how can I achieve that the bean1 uses his own entity manager all the times?


      Thanks for your help!
      Thierry

        • 1. Re: Lazy Load Execption with Seam managed persistence context, not so with container managed pc
          lvdberg

          The nice thing of the seam open session in conversation is that Seam will take care of loading the parts of the object graph including all stuff annotated as to-be-loaded-lazy.


          Great, but this doesn't mean these collections are kept for you in memory. So lazy loading exceptions in the observed methods are still possible especially when you try to updates these lazy-loaded collections.


          A simple solution would be change the query so that you always load all necessary collections, or if not possible because of size, leave the updates completely in the same bean.


          Another possible problem is cache of the user session. We are developing an application where all users must refresh their view when updates are made. Soubnds simple, but will not work with normal events. We use an appliaction scoped bean which receives the event and this beans resends in to all user . There we found the problem of the user cache, the query was NOT reloaded because no change was detected. We had to explicitily clean the entitymanager to allow for the refresh.


          Im am getting annoying with this last bit: insert logs into your create and destroy methods, this gives you a very good idea what's going on. Seam is very active in destroying its unreferenced stuff, so you loose data before you know it.


          Hopefully this helps a bit,


          Leo

          • 2. Re: Lazy Load Execption with Seam managed persistence context, not so with container managed pc
            coresystems_rit

            Hi Leo


            Thanks for your answer. What does confuse me is the fact, that the observed method reloads the data with a query from the database but it looks like it doesn't use the entitiy manager which is assigned to the sfsb (scopetype.session). As far as I do understand, the persistence context should stay alive as long as the session is running. Therefor it shouldn't display a lazy loaded exception because the data should still be in the persistence context.


            One solution that works (but is somehow ugly) is that i only set a boolean value (e.g. datamodified) to true and set the datamodel scope to page. In the method where the data gets loaded for the datamodel I first check if the boolean value is true. If this is the case I'm reloading the database (wouldn't make sense to just reload all the time).


            As I am not very excited on using eager loading, this is the workaround I will use. But still I would be interested why this scenario doesn't work. Why I do get a lazy loading exception when I use a seam managed persistence context in a session scoped bean. Especially why not the same instance of the entity manager reloads the data in the observe method as it handles in the jsf rendering cycle.


            Thanks for your help!


            Thierry

            • 3. Re: Lazy Load Execption with Seam managed persistence context, not so with container managed pc
              lvdberg

              The memory management of Seam is impressive, meaning Seam dosn't save things in memory if not really,  absolutely necessary.


              neither does an Entitymanager leave a connection to the databaase open all the time, it only creates the connection when necessary.


              The same goes for the EntityManager itself. At the moment you call a method on a bean, the @In annotated attributes are injected. As far I can see this is also true for session and application scoped beans, so there are no everlasting references in these beans.


              Leo


              • 4. Re: Lazy Load Execption with Seam managed persistence context, not so with container managed pc
                coresystems_rit

                Ah ok. Well this would explain the problem. Should be configurable in my eyes. What are other users thinking about this?


                Thanks for your help!


                Thierry