4 Replies Latest reply on Nov 30, 2004 3:31 AM by camel

    Entity bean best practices

      For this question, assume that the web container and EJB container are on seperate machines.

      Machine 1 hosts the EJB3 beans. Let's say there's two entity beans: Order and LineItem, the relationship between them is fairly simple -- each Order contains many LineItems. The Order entity is set to LAZY FETCH the LineItems.

      Machine 1 also hosts a session bean with a single method getOrderById(). The implementation is obvious.

      Machine 2 is the webserver. The webserver calls getOrderById on the session bean. The session bean uses the Entity Manager to find the Order and returns it to the webserver.

      Machine 2 now has an entity bean it can work with, however, if the webserver calls order.getLineItems(), there's an exception thrown because the webserver (obviously) can't lazy load the LineItems.

      With all that said, does anyone here have recommendations for implementing something like what I've described above. I want to take advantage of lazy loading, but then what's the best way to give clients (the webserver in this case) access to the lazy-loaded data? I imagine there must be a better way than having the session bean also contain a getLineItemsByOrder() method.

      Essentially, I want the clients to be able to do { Order x = getOrderById(order_id); Collection y = x.getLineItems() }. All while using lazy loading (so the second call, "x.getLineItems()", should make another RMI call to get the get the LineItems.

        • 1. Re: Entity bean best practices
          bill.burke

          YOu cannot do what you want. Remember, what you have is a detached POJO with no knowledge of remoteness. EJB 3.0 Entities are POJOs. They have no notion of remoteness.

          You can have control over relationships with your query. For instance, if you have lazy for the line item, you can use a fetch to prefetch the relationship:

          "from Order o left join fetch o.lineItems where id=55"

          This query SHOULD work, but i'm not sure it WILL work because we've not tested it yet.

          Bill

          • 2. Re: Entity bean best practices

            In a test in which questions and definitions are associated in a ManyToMany-Relation and in which Macromedia Flex is involved the following query won't work but throw a LazyInitializationException.

            Best regards
            Jan Prill


            The query:

            public List findByMarkup(String markup) {
             return manager
             .createQuery("from Question q left join fetch q.definitions where q.markup = :markup")
             .setParameter("markup", markup).listResults();
             }


            The full stacktrace:

            17:42:27,046 ERROR [LazyInitializationException] failed to lazily initialize a c
            ollection - no session or session was closed
            org.hibernate.LazyInitializationException: failed to lazily initialize a collect
            ion - no session or session was closed
             at org.hibernate.collection.AbstractPersistentCollection.initialize(Abst
            ractPersistentCollection.java:179)
             at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPe
            rsistentCollection.java:49)
             at org.hibernate.collection.Bag.size(Bag.java:207)
             at flashgateway.io.DataOutput.writeObjectArray(DataOutput.java:703)
             at flashgateway.io.DataOutput.writeObject(DataOutput.java:166)
             at flashgateway.io.DataOutput.writeASObject(DataOutput.java:387)
             at flashgateway.io.JavaBeanSerializer.writeObject(JavaBeanSerializer.jav
            a:96)
             at flashgateway.io.DataOutput.writeObject(DataOutput.java:174)
             at flashgateway.io.DataOutput.writeObjectArray(DataOutput.java:713)
             at flashgateway.io.DataOutput.writeObject(DataOutput.java:166)
             at flashgateway.io.DataOutput.writeASObject(DataOutput.java:387)
             at flashgateway.io.JavaBeanSerializer.writeObject(JavaBeanSerializer.jav
            a:96)
             at flashgateway.io.DataOutput.writeObject(DataOutput.java:174)
             at flashgateway.io.DataOutput.writeObjectArray(DataOutput.java:659)
             at flashgateway.io.DataOutput.writeObjectArray(DataOutput.java:681)
             at flashgateway.io.DataOutput.writeObject(DataOutput.java:107)
             at flashgateway.io.MessageSerializer.writeBody(MessageSerializer.java:15
            7)
             at flashgateway.io.MessageSerializer.writeMessage(MessageSerializer.java
            :113)
             at flashgateway.filter.SerializationFilter.invoke(SerializationFilter.ja
            va:119)
             at flashgateway.Gateway.invoke(Gateway.java:217)
             at flashgateway.controller.GatewayServlet.service(GatewayServlet.java:69
            )
             at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
            icationFilterChain.java:237)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
            ilterChain.java:157)
             at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFi
            lter.java:75)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
            icationFilterChain.java:186)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
            ilterChain.java:157)
             at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperV
            alve.java:214)
             at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv
            eContext.java:104)
             at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.jav
            a:520)
             at org.apache.catalina.core.StandardContextValve.invokeInternal(Standard
            ContextValve.java:198)
             at org.apache.catalina.core.StandardContextValve.invoke(StandardContextV
            alve.java:152)
             at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv
            eContext.java:104)
             at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrinc
            ipalValve.java:66)
             at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv
            eContext.java:102)
             at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(Securit
            yAssociationValve.java:153)
             at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv
            eContext.java:102)
             at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValv
            e.java:54)
             at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv
            eContext.java:102)
             at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.jav
            a:520)
             at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.j
            ava:137)
             at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv
            eContext.java:104)
             at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.j
            ava:118)
             at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv
            eContext.java:102)
             at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.jav
            a:520)
             at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineVal
            ve.java:109)
             at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValv
            eContext.java:104)
             at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.jav
            a:520)
             at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
            
             at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:16
            0)
             at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java
            :799)
             at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.proce
            ssConnection(Http11Protocol.java:705)
             at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java
            :577)
             at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadP
            ool.java:683)
             at java.lang.Thread.run(Thread.java:595)
            17:42:27,062 INFO [STDOUT] Error: failed to lazily initialize a collection - no
             session or session was closed
            17:42:27,062 INFO [STDOUT] Error: null
            


            • 3. Re: Entity bean best practices
              bill.burke

              Either traverse the relationship on the server side, or change your fetch policy to EAGER. This isn't a bug....Its a feature.

              Bill

              • 4. Re: Entity bean best practices
                camel

                See Hibernate.initialize() (it's in hibernate 2, not sure if hibernate3 / EJB3 has it).