6 Replies Latest reply on Jun 21, 2008 4:26 PM by svetzal

    Dealing with concurrency and LazyInitializationExceptions

    svetzal

      Hi Folks,


      I'm having some considerable difficulty figuring out what to do with a problem I'm having in an application we're building.


      The application is basically displaying data from a database (updated by another separate application) on a UI and provides navigation of that data.


      We have many refresh areas on the page, several of which are updated at different times during navigation. These range from a Tree control to a breadcrumb trail and a mix of other contextual data.


      The object graph is very large, and we must aggressively lazy-load. The database is also very complex and the queries required to load data are fairly slow running - which makes lazy-loading even more important. And we need to be careful to display as up-to-date data as possible, so we are regularly hitting the database to re-read data.


      So here comes my problem. Ajax requests cause concurrent access to objects, so we have multiple threads on the server dealing with basically the same objects even within the same user session, all to refresh different parts of the UI as the user clicks around and various Ajax regions auto-refresh.


      So we get these LazyInitializationExceptions, because we end up quite often with two different Session beans trying to service two different requests and trying to lazy-load two different parts of the same bean to service different refresh areas.


      We've tried all we can to serialize access to these beans with extensive use of @Synchronized annotations through our Action classes and this has cleaned up the majority of these kinds of problems, except what we're seeing now when two different @Synchronized components need to lazy-load two different parts of the same bean, and we end up with threads fighting to associate the same object each with its own Hibernate session, and then KABOOM.


      So, I'm sitting back thinking. What am I missing?


      I hate the idea that in order to solve these problems the end result seems to be serializing all requests through a single @Synchronized Action component so that we never process requests concurrently that might need to reconstitute different areas of the object graph. Never mind the performance implications of this (why am I being forced to effectively write a single-threaded app???!!!), I just hate the way this whole antipattern is developing.


      So again, what am I missing? I need some concrete ideas or examples of how to break this spiral.

        • 1. Re: Dealing with concurrency and LazyInitializationExceptions
          svetzal

          Oh, one thing I didn't add above is that we're using Seam managed Hibernate sessions and not JavaEE PersistenceContext.


          Our app has been forced into using XML persistence mappings so we can minimize code change in dealing with database vendor specific schema differences. Plus we make use of filters for permission based object filtering, javaassist object proxies to help with lazy loading, and other techniques that I don't believe are available using a PersistenceContext.

          • 2. Re: Dealing with concurrency and LazyInitializationExceptions
            gjeudy

            What JSF-ajax library are you using? Are you using Richfaces? If so I think you can use some ajax attributes like eventQueue, requestDelay and ignoreDupResponses to help to control what the client sends to the server and alleviate some of the concurrency issues you are seeing in the server.
            See: RichFaces Ajax Attributes.


            As for Seam managed hibernate sessions versus JavaEE entityManager I don't think it makes a difference in the problem you are tackling.


            PS: I am using JPA and Hibernate as a persistence provider and I confirm it can still read XML hibernate mapping (using hibernate proprietary features) and it also uses javaassist object proxies for lazy loading. I think JPA is mainly a different API limiting you in some respects but you hardly lose any proprietary hibernate features that are still active under the hood. You have to be careful however, if you map an entity with an hbm file the default loading strategy is lazy load for associations, on the contrary if you use a JPA annotation or orm.xml file the default will be eager load in most cases. In both cases you can still choose to use EntityManager and PersistenceContext interfaces for your application code.


            Have you looked at persistence:filters option ? This is supported in Seam if you have Hibernate as the JPA provider.


            Finally, can you please provide an example of the issue you are having? We might be able to help better if you give more details.


            Thanks,
            -Guillaume

            • 3. Re: Dealing with concurrency and LazyInitializationExceptions
              svetzal

              Guillaume Jeudy wrote on Jun 20, 2008 15:11:

              What JSF-ajax library are you using? Are you using Richfaces?


              Yes, we're using RichFaces and using one specific eventsQueue everywhere... Would the issue not still occur though across multiple concurrent independent client systems? I'm not entirely sure at this point where sessions are bound, whether at transactional boundaries or thread boundaries.



              Finally, can you please provide an example of the issue you are having? We might be able to help better if you give more details.


              Thanks, Guillaume - I'll see what I can boil down.

              • 4. Re: Dealing with concurrency and LazyInitializationExceptions
                gjeudy

                Yes you are right the issue could still occur with multiple concurrent independent client systems. Have you tried setting a requestDelay ? From what I understand it can help in removing duplicate AJAX request from the eventsQueue if the client already got a response for an identical request, thus reducing concurrency on the server side.


                If you are hitting the server with multiple concurrent independent client systems then aren't you hitting different instances of your action beans (each client system has it's own session and conversations right)? In which case there would not be a concurrency issue at least not at the action bean level (could be at DB level).


                As for sessions if you are using SMPC then your persistence context(session context) is bound to the conversation scope. The Session object itself is bound to the transaction scope.



                Seam uses two transactions per request; the first spans the beginning of the restore view phase (some transaction managers begin the transaction later at the beginning of the apply request values phase) until the end of the invoke application phase; the second spans the render response phase

                Seam doc link

                • 5. Re: Dealing with concurrency and LazyInitializationExceptions
                  gjeudy

                  you were talking of thread boundaries, just to be precise, typically an application server will assign 1 thread per request. Which means each thread should have it's own transaction and session objects.

                  • 6. Re: Dealing with concurrency and LazyInitializationExceptions
                    svetzal

                    Guillaume Jeudy wrote on Jun 20, 2008 19:59:

                    If you are hitting the server with multiple concurrent independent client systems then aren't you hitting different instances of your action beans (each client system has it's own session and conversations right)? In which case there would not be a concurrency issue at least not at the action bean level (could be at DB level).


                    Yes, I tested for this yesterday - finally set up Firefox with a couple dozen profiles and launched them all at the app.


                    Single profile, multiple windows, stressing the same beans in one session can show the problem, multiple profiles stressing multiple sessions don't show the problem at all.


                    It is compelling to want to outject partially loaded object graphs into a scope for use in the templates, but from what I can see lately this is dangerous - because if the same object instance is requested concurrently to resolve different parts of its graph they're each going to try and associate the object with their session and we'll see breakage.


                    This then pressures the developer to ensure that only small pre-populated portions of object graphs are outjected. Or to plan carefully to broker access to the object graph serially through a Synchronized bean component.


                    Do you think these are correct statements then with regards to current Seam behaviour?