3 Replies Latest reply on Mar 1, 2012 5:15 PM by heapifyman heapifyman

    AS 7.1 kitchensink example and LazyInitializationException in resteasy

    heapifyman heapifyman Newbie

      Hello all,

       

      I tried out the kitchensink example for JBoss AS 7.1 Final and extended the Member entity with a

      @OneToMany(orphanRemoval = true)
      private List<Posting> postings = new ArrayList<Posting>();
      
      
      

       

      where Posting is a trivial entity:

      @Entity
      @XmlRootElement
      public class Posting implements Serializable {
                private static final long serialVersionUID = -6566853381734731917L;
      
                @Id
                @GeneratedValue
                private Long id;
      
                @NotNull
                @Size(min = 3, max = 140)
                private String message;
      
              // Getters and setters
             // ...
      }
      

       

      When I now try to invoke any one of the rest service methods in MemberResourceRESTService I get a LazyInitializationException (stacktrace at the bottom of this post).

      I think I understand why this happens, but I would like to ask what would be a best-practice way of avoiding such an exception?

       

      I thought I could add an @XmlTransient annotation at the postings property but that did not help. Even if it did it would have been not very flexible because I would want to exclude the postings from being transmitted in the response when calling listAllMembers() but I would like to include them when calling lookupMemberById(@PathParam("id") long id).

       

      Thanks in advance for any ideas.

       

      Also, I apologise if this question is somehow off-topic here.

       

      Stacktrace:

      11:02:13,636 Schwerwiegend [org.jboss.resteasy.core.SynchronousDispatcher] (http--127.0.0.1-8080-4) Failed executing GET /members/0: org.jboss.resteasy.spi.WriterException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.jboss.as.quickstarts.kitchensink.model.Member.postings, no session or session was closed

                at org.jboss.resteasy.core.ServerResponse.writeTo(ServerResponse.java:262) [resteasy-jaxrs-2.3.1.GA.jar:]

                at org.jboss.resteasy.core.SynchronousDispatcher.writeJaxrsResponse(SynchronousDispatcher.java:585) [resteasy-jaxrs-2.3.1.GA.jar:]

                at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:506) [resteasy-jaxrs-2.3.1.GA.jar:]

                at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:119) [resteasy-jaxrs-2.3.1.GA.jar:]

                at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208) [resteasy-jaxrs-2.3.1.GA.jar:]

                at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55) [resteasy-jaxrs-2.3.1.GA.jar:]

                at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50) [resteasy-jaxrs-2.3.1.GA.jar:]

                at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.10.Final.jar:]

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.10.Final.jar:]

                at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.10.Final.jar:]

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.10.Final.jar:]

                at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.10.Final.jar:]

                at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:161) [jbossweb-7.0.10.Final.jar:]

                at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java) [jbossweb-7.0.10.Final.jar:]

                at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.0.Final.jar:7.1.0.Final]

                at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:154) [jboss-as-web-7.1.0.Final.jar:7.1.0.Final]

                at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.10.Final.jar:]

                at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.10.Final.jar:]

                at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.10.Final.jar:]

                at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.10.Final.jar:]

                at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.10.Final.jar:]

                at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.10.Final.jar:]

                at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.10.Final.jar:]

                at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_03]

      Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.jboss.as.quickstarts.kitchensink.model.Member.postings, no session or session was closed

                at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:393) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]

                at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:385) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]

                at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:378) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]

                at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:112) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]

                at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:266) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]

                at com.sun.xml.bind.v2.runtime.reflect.Lister$CollectionLister.iterator(Lister.java:282)

                at com.sun.xml.bind.v2.runtime.reflect.Lister$CollectionLister.iterator(Lister.java:269)

                at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:133)

                at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:159)

                at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:356)

                at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:597)

                at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:338)

                at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:498)

                at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323)

                at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:251)

                at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:74) [jboss-jaxb-api_2.2_spec-1.0.3.Final.jar:1.0.3.Final]

                at org.jboss.resteasy.plugins.providers.jaxb.AbstractJAXBProvider.writeTo(AbstractJAXBProvider.java:121) [resteasy-jaxb-provider-2.3.1.GA.jar:]

                at org.jboss.resteasy.core.interception.MessageBodyWriterContextImpl.proceed(MessageBodyWriterContextImpl.java:117) [resteasy-jaxrs-2.3.1.GA.jar:]

                at org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor.write(GZIPEncodingInterceptor.java:98) [resteasy-jaxrs-2.3.1.GA.jar:]

                at org.jboss.resteasy.core.interception.MessageBodyWriterContextImpl.proceed(MessageBodyWriterContextImpl.java:123) [resteasy-jaxrs-2.3.1.GA.jar:]

                at org.jboss.resteasy.core.ServerResponse.writeTo(ServerResponse.java:250) [resteasy-jaxrs-2.3.1.GA.jar:]

                ... 25 more

        • 1. Re: AS 7.1 kitchensink example and LazyInitializationException in resteasy
          Scott Marlow Master

          As you would want, the postings collection is fetched lazily, however that gets broken if the entity manager goes out of scope.  The general rule is to keep the entity manager in scope long enough to fetch the collection contents. 

           

          General rules for when the entity manager will go out of scope (causing the lazy initialization error if the collection is not yet fetched):

           

          1.  If you use a transactional scoped entity manager under the control of a JTA transaction, the entity manager will go out of scope when the jta transaction ends.

          2.  If you use a transactional scoped entity manager without the control of a JTA transaction, the entity manager will go out of scope immediately after each entity manager invocation.

           

          If you switch to using an extended persistence context (from stateful session beans only), the scope of the entity manager will be until the statefule session bean is destroyed.  Perhaps you could still use the transaction scoped entity manager if you ensure that collection is referenced from with the transaction.

           

           

          @javax.ejb.Stateful
          public class YourStatefulBean {
          
              @PersistenceContext(unitName = "mypu", type = PersistenceContextType.EXTENDED)
                  EntityManager em;  // scope of entity manager will be until instance of YourStatefulBean is destroyed
          

           

           

          Scott

          1 of 1 people found this helpful
          • 2. Re: AS 7.1 kitchensink example and LazyInitializationException in resteasy
            heapifyman heapifyman Newbie

            I am in case 1. EM under control of JTA transaction, I suppose.

             

            I had changed the example's MemberResourceRESTService to be a SLSB:

            /**
             * JAX-RS Example
             * 
             * This class produces a RESTful service to read the contents of the members
             * table.
             */
            @Path("/members")
            @Stateless
            public class MemberResourceRESTService {
            
                 @GET
                 @Produces(MediaType.APPLICATION_JSON)
                 public List<Member> listAllMembers() {
                      ...
                 }
            
                 @GET
                 @Path("/{id:[0-9][0-9]*}")
                 @Produces(MediaType.APPLICATION_JSON)
                 public Member lookupMemberById(@PathParam("id") long id) {
                      ...
                 }
            }
            

             

            Turning it into a Stateful SessionBean and using @PersistenceContext(type = PersistenceContextType.EXTENDED) works but that kind of feels "wrong" for a RESTful Service.

            Also, this way, the postings property is also accessed for every Member when returning the list of all members from listAllMembers().

             

            I guess my questions really is:

            is there a way to configure/change above RESTful Service so that it ignores Member's "postings" property when returning the list of all Members fom listAllMembers() but includes "postings" when only returning one Member from lookupMemberById(@PathParam("id") long id)?

             

            Thanks

            • 3. Re: AS 7.1 kitchensink example and LazyInitializationException in resteasy
              heapifyman heapifyman Newbie

              Ok, so I figured out now that JBoss AS 7.1 includes resteasy-jackson-provider, so resteasy uses jackson as the default provider when (un)marshalling from/to JSON.

              And jackson does not use @XMLTransient but its own annotation @JsonIgnore.

              If I apply that to the postings property that property is ignored during marshalling and thus I don't get any LazyInitializationException anymore, even without using a Stateful SessionBean and Extended PersistenceContext.