8 Replies Latest reply: Oct 16, 2012 2:26 AM by gimbal2 RSS

    JAX-WS + Hibernate - How to avoid Lazy init exceptions

    600732
      Hi.

      I have a JAX-WS application, which returns data objects, that were fetched from a Hibernate Database backend (Oracle 10g or Oracle 11g).
      It works fine, unless the object has depencies, which should also be returned. Then JAX-WS (or JAX-B) finds that the Hibernate Session has been closed.
      How can I (using a JAX-WS Handler?) open a session with every request from a Web Service client?

      e.g. at the moment
      ....
      @WebMethod
      public HibernateObject testMethod()
      {
         HibernateSession session = HibernateUtil.openSession();
         HibernateObject obj = session.getHibernateObject(...)
         session.close();
         return obj; //this can not always be serialised, as the object may not exist any more.
      }
      ...
      what I would like is some kind of trick for JAX-WS, such that I can say
      MyJaxWsHandler extends JaxWsHandlers
      {
         public handleMessage( )
         {
            if (start message)
            //set up the Hibernate session
            else (end message)
            //close Hibernate session
         }
      }
      then my Web Service would look like:
      ....
      @WebMethod
      public MyHibernateObject testMethod()
      {
         HibernateSession session = getHibernateSession();
         MyHibernateObject obj = session.getHibernateObject(...)
         //session.close(); //not needed / appropriate
         return obj; //object can be serialised, because Hibernate session is open until web service method is closed.
      }
      ...
      Thanks for your ideas.

      Martin

      Edited by: mac24nz on Jun 8, 2011 3:29 AM
        • 1. Re: JAX-WS + Hibernate - How to avoid Lazy init exceptions
          Kayaman
          Don't use lazy loading here, since you want to transport the complete object graph anyways, there's no advantage to loading it lazily.

          There's no "tricks" here.
          • 2. Re: JAX-WS + Hibernate - How to avoid Lazy init exceptions
            600732
            Hi Kayaman

            Often I'm reusing the same Hibernate code, outside of JAX-WS, where lazy loading is an advantage.
            How would I go about disabling lazy loading anyway? can I disable it just for a single Hibernate call? (Some parameter in the Hibernate session perhaps?)

            So there is no way to get JAX-WS to initialise the session with each call and close it afterwards? some servlett / JAX-WS Handler code?

            Thanks
            • 3. Re: JAX-WS + Hibernate - How to avoid Lazy init exceptions
              Kayaman
              mac24nz wrote:
              Often I'm reusing the same Hibernate code, outside of JAX-WS, where lazy loading is an advantage.
              How would I go about disabling lazy loading anyway? can I disable it just for a single Hibernate call? (Some parameter in the Hibernate session perhaps?)
              If you're using straight Hibernate, without going through JPA, I'd probably try to fetch it with the Criteria API. Depending on your code of course.
              So there is no way to get JAX-WS to initialise the session with each call and close it afterwards? some servlett / JAX-WS Handler code?
              I'm not saying there's no way, I'm saying that it's not a very good solution.
              You know that you'll be sending the object graph over webservice, so you know that you'll need all the data (so lazy loading is useless and trying to do tricks to support it is a waste of time).

              Or you could go recursively through your object graph and trigger the lazy loading where needed, when your session is still available.
              • 4. Re: JAX-WS + Hibernate - How to avoid Lazy init exceptions
                643310
                I faced a similar problem once, when the object graph was too deep and nested, so had to go for Lazy loading. Still one of my clients needed the complete object graph.

                I used Spring + JPA.

                This is how I solved it (not very happy with this approach though, but couldn't think of anything better then):
                1. The service layer will still not load the complete object graph because of lazy loading. The transaction propagation level was to set to REQUIRED. Most of the clients will use this layer.
                2. A wrapper layer which will be invoked only by specific clients which needs the complete object graph loaded. The transaction propagation level was REQUIRED again for this. In this invoke the service and manually invoke the children to trigger the loading into the object graph. As the children are accessed within the transaction there will not be any problems.
                • 5. Re: JAX-WS + Hibernate - How to avoid Lazy init exceptions
                  600732
                  So thanks for your help.

                  I've now found a solution using JAX-WS Handlers. Here is my pseudo java code implementation.
                  .....
                  @WebService()
                  @HandlerChain(file = "TestWebService_handler.xml")
                  public class TestWebService {
                  
                      @Resource
                      WebServiceContext webContext;
                  
                     protected Session getHibernateSession()
                  {
                  
                          MessageContext context = webContext.getMessageContext();
                          HibernateSession session = (HibernateSession)context.get("HIBERNATE_SESSION");
                          return session;
                  }
                  
                   @WebMethod
                  public MyHibernateObject testMethod()
                  {
                  HibernateSession session = getHibernateSession();
                  MyHibernateObject obj = session.getHibernateObject(...)
                  return obj; //object can be serialised, because Hibernate session is open until web service method is closed.
                  }
                  .....
                  public class TestHandler <SOAPMessageContext> implements
                          SOAPHandler {
                      public boolean handleMessage(SOAPMessageContext lmc) {
                          Boolean outboundProperty = (Boolean) lmc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
                          HibernateSession test = null;
                          if (outboundProperty.booleanValue()) {
                              //direction = outbound
                              test = (HibernateSession) lmc.get("HIBERNATE_SESSION");
                              lmc.remove("HIBERNATE_SESSION");
                              lmc.getMessage().toString(); //force creation of soap message - then the object tree will be read from hibernate
                              test.close(); //close Hibernate session
                          } else {
                              //direction = inbound
                              test = MyHibernateUtil.createSession();
                              lmc.put("HIBERNATE_SESSION", test);
                              lmc.setScope("HIBERNATE_SESSION", MessageContext.Scope.APPLICATION);
                          }
                          return true;
                      }
                  }
                  ...does anyone see any problem with this solution? It seems to work just fine.....

                  Edited by: mac24nz on Dec 21, 2010 1:33 PM

                  Edited by: mac24nz on Jun 8, 2011 3:31 AM
                  • 6. Re: JAX-WS + Hibernate - How to avoid Lazy init exceptions
                    drenda81
                    HI,
                    I'm the opposite problem. I'm using a session per request pattern with Hibernate. I'm using Jax-RS Jersey. I'm using lazy properties in all my entity but when the object is sent to the network is sent all the graph --> because the hibernate session is open.

                    I'd like to send only some data to the client that I would choose programatically.

                    Any suggestion?

                    Thanks
                    • 7. Re: JAX-WS + Hibernate - How to avoid Lazy init exceptions
                      Kayaman
                      Don't hijack other people's threads, post a new one instead.

                      As for your question, it seems you'll need to do some manual unproxying. Search for hibernate unproxy.
                      • 8. Re: JAX-WS + Hibernate - How to avoid Lazy init exceptions
                        gimbal2
                        That or don't send JPA entities to the client; create an object model that is tailored to the client's needs. I don't want to use the term DTO because it is so outdated, but sometimes they are still useful.