3 Replies Latest reply on May 19, 2006 7:04 PM by DavidLily

    Lazy Initialization Exceptions

    busitech Level 1
      Our Java naturally classes contain properties which are relationships to other classes - either one to many or many to one. Due to the fact that these relationships are so intertwined, many given objects end up referencing a large portion of the database if one were to recursively follow all of the nested relationships. As such, we desire to have the option of not loading certain relationships when the data is not needed.

      We use EJB 3.0 (JBoss implementation using Hibernate) for object persistence. It allows the option of uninitialized collections and other referenced objects.

      The Flex process of serialization to AMF causes serious problems for this design. It tries to touch all of these properties while building the binary representation for sending over the wire. This triggers an immediate attempt to initialize the objects which are still in the uninitialized state.

      This causes the LazyInitializationException to be thrown by the O/R framework - because the transaction is already closed (which effectively means the call to the DAO has returned).

      The community only offers two suggestions, both which do not work with Flex (or Flash Remoting for that matter). T

      he first is simply initializing everything ahead of time. This does not work because eventually you have to draw the line somewhere, and the Flex serialization routines will find that line and try to cross it.

      The second is the open session in view pattern, meaning that we open the transaction as soon as the Flex client makes a request, and close it only when the last response has been made. This does not work either, because Flex would end up initializing everything during serialization.

      I have gone to the extent to writing a custom aspect to intercept returning calls from my DAO and null out the Hibernate proxies. This worked until I tried to use it for uninitialized many to one relationships. Nulling them out actually deletes my relationship in the database!

      The only solution I see is to add intelligence to the Flex serialization techniques which watch for this scenario, and avoid triggering the lazy initialization.

      Any suggestions would be appreciated.
        • 1. Re: Lazy Initialization Exceptions
          jvroom
          We have the same problem with the hibernate assembler (not surprising!).

          Just after beta 3 went out, I changed the code so that if your association properties are marked with "lazy=true" that we do not do a deep traversal on the properties of that object for the "createSequence" operation. Only the id of the referenced item is accessed in this case. In other words, when your assembler has a lazy association, you can return a hollow instance for any properties which reference lazy associations. For single-valued associations, this is great because hibernate makes the id of the item available even if the properties have not yet been fetched. For multi-valued associations, hibernate does not even fetch the list of referenced items by default so we still need to "touch" the collection while the transaction is open to make sure the ids of the reference items are fetched.

          In the hibernate assembler in beta3, we have a method which fetches all of the properties of all objects - i.e. it pulls in the entire reachable sub-graph of objects which is what the sequencing code in beta 3 will also do before returning any object from the assembler. In the version post-beta 3, the code only fetches the state of non-lazy associations, and fetches just the first level of objects for multi-valued associations.

          So in beta3, you could just live with this deep traversal and this restriction will be removed in the final release. Another option is to turn off auto-sync-enabled since the deep traversal is only required if you clients are receiving changes made.
          • 2. Re: Lazy Initialization Exceptions
            busitech Level 1
            I spent considerable time last year documenting this concept for the people at Hibernate, in an attempt to show them clearly how the library needs enhancement to accomodate this scenario, and volunteered to develop the patch. They refused to accept the changes at the highest levels of the team.

            I think you realize we are not using the hibernate assembler, but EJB3.0 through the java adapter, so the changes made to the hibernate assembler would not effect our application...

            The cat's meow would be for Flex to interrogate the annotations of the Java class at runtime. This would require Java 1.5, but that's OK with us! When it finds either of these annotations, it would not traverse the relationship:

            @ManyToOne(fetch=FetchType.LAZY)
            @OneToMany(fetch=FetchType.LAZY)

            Please note that the default for @OneToMany is FetchType.LAZY, so the annotation would really look like this:

            @OneToMany

            Annotations could be used to a great extent in the java side of Flex, to recognize security domain, the type of relationships present on a Class (as above), and especially the primary key. The @Id annotation should be used in lieu of the info in an XML configuration file.

            For now, we have further modified our AOP aspect to make it work for the many-to-one association, so we have now have a solution developed to get around this problem. All associations now come back null to the Flex java adapter unless initialized in advance.
            • 3. Re: Lazy Initialization Exceptions
              DavidLily
              quote:

              Originally posted by: busitech
              Our Java naturally classes contain properties which are relationships to other classes - either one to many or many to one. Due to the fact that these relationships are so intertwined, many given objects end up referencing a large portion of the database if one were to recursively follow all of the nested relationships. As such, we desire to have the option of not loading certain relationships when the data is not needed.

              We use EJB 3.0 (JBoss implementation using Hibernate) for object persistence. It allows the option of uninitialized collections and other referenced objects.

              The Flex process of serialization to AMF causes serious problems for this design. It tries to touch all of these properties while building the binary representation for sending over the wire. This triggers an immediate attempt to initialize the objects which are still in the uninitialized state.

              This causes the LazyInitializationException to be thrown by the O/R framework - because the transaction is already closed (which effectively means the call to the DAO has returned).

              The community only offers two suggestions, both which do not work with Flex (or Flash Remoting for that matter). T

              he first is simply initializing everything ahead of time. This does not work because eventually you have to draw the line somewhere, and the Flex serialization routines will find that line and try to cross it.

              The second is the open session in view pattern, meaning that we open the transaction as soon as the Flex client makes a request, and close it only when the last response has been made. This does not work either, because Flex would end up initializing everything during serialization.

              I have gone to the extent to writing a custom aspect to intercept returning calls from my DAO and null out the Hibernate proxies. This worked until I tried to use it for uninitialized many to one relationships. Nulling them out actually deletes my relationship in the database!

              The only solution I see is to add intelligence to the Flex serialization techniques which watch for this scenario, and avoid triggering the lazy initialization.

              Any suggestions would be appreciated.