Hibernate failed to lazily initialize

Help
Fred T
2009-04-22
2012-12-13
  • Fred T
    Fred T
    2009-04-22

    Hi All,

    I fetch objects through the OpenSwing Servlet. I use the standard serialisation in combination with Hibernate.

    For grids it works like a charm. When I click the grid and load a detail form...
    The Form controller fetches the object and returns the response. (through the servlet again).

    The forms displays well and works fine... I can edit and save the form...
    But while loading the form data (double clicking the grid) I get a lot of errors for all lazy initialised attributes. (they are lazy initialised because I will not use them in this form)

    I'm getting errors like this:

    in org.openswing.swing.form.model.client.VOModel.setValueObject():
    Error while setting the value object attribute 'distributeurs.referenceTrade'
    java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.openswing.swing.form.model.client.VOModel.setValueObject(VOModel.java:266)
        at org.openswing.swing.form.client.Form.loadData(Form.java:709)
        at org.openswing.swing.form.client.Form.access$1100(Form.java:54)
        at org.openswing.swing.form.client.Form$6.run(Form.java:635)
        at java.awt.event.InvocationEvent.dispatch(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at org.openswing.swing.util.client.ApplicationEventQueue$InternalEventQueue.dispatchEvent(ApplicationEventQueue.java:129)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)
    Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
        at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:57)
        at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
        at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150)
        at fta.hibernate.pojo.dynaco.Distributeurs$$EnhancerByCGLIB$$2b62eec5.getReferenceTrade(<generated>)
        ... 17 more

    Is there a solution to this?

    Errors come from the VOModel method setValueObject
    Is there a special VOModel to use with Hibernate? (that checks if attributes are lazy initialised?)

    The application runs fine but I would like to eliminate those exceptions...

    Any help would greatly be appreciated.

    Kind regards,
    Fred

     
    • mcarniel
      mcarniel
      2009-04-26

      I believe you should follow both these rules:
      - never use lazy initialization when retrieving entities from the ORM; this avoid to fire a 'lazy initialization exception' on the client-side
      - include hibernate.jar and other dependencies libraries in client-side tier; this avoid to fire ClassNotFoundException on the client-side

      Anyway, OpenSwing includes a sample application (demo9) and I suggest you to look at it: it is a two tier (not 3 tier) app but some
      issues arise in this app too, see for instance "EmpDetailFrameController" class and the way used to fetch the detail value object...

       
    • Fred T
      Fred T
      2009-04-26

      Thank you very much for the reply. It works!

      I replaced my HQL by a criteria and initialised all attributes that where lazy loaded like this

      Criteria criteria = sess.createCriteria(Service.class);
      criteria.setFetchMode("serviceDetails", FetchMode.JOIN);
      criteria.setFetchMode("serviceFileses", FetchMode.JOIN);
      criteria.setFetchMode("serviceStatustrackings", FetchMode.JOIN);
      criteria.setFetchMode("distributeurs", FetchMode.JOIN);

      criteria.add( Restrictions.idEq(id));
      Service vo = (Service)criteria.uniqueResult();
           
      return new VOResponse(vo);

      It would be a nice if openswing permitted to use lazy loading and only give errors if we try to read/write a property of the lazy initialised attributes...
      Now the org.openswing.swing.form.model.client.VOModel traverses the object tree completely and stops traversing if an object is 'null'.

      a code snippet of the openswing VOModel class in the setValueObject method:
      // check if the inner v.o. is null...
      if(obj == null) {
              if (!createInnerVO)
                    break;
              else
                     obj = (ValueObject)readMethods[i].getReturnType().newInstance();
      }

      Would it be possible to implement a VOHibernateModel that adds a check if obj is lazily initialised?

      Either way it works now, thank you very much for your reply!

      Kind regards,
      Fred

       
    • Fred T
      Fred T
      2009-06-01

      To come back to this matter... If I'm not allowed to use lazy loading, I end up transferring too much data.

      I've added the possibility to tell the Form which attributes will be lazily loaded...

      private Form mainForm;
      //...
      mainForm.getAttributeNamesToIgnore().add("distributeurs");
      mainForm.getAttributeNamesToIgnore().add("serviceDetails");
      //...

      To make this possible I've slightly altered the OpenSwing framework as follows:

      In the class: org.openswing.swing.form.client.Form  I added an attribute + it's getter (left out in the code below)

      private Set attributeNamesToIgnore = new TreeSet();

      public Set getAttributeNamesToIgnore() {
          return attributeNamesToIgnore;
      }

      In the class: org.openswing.swing.form.model.client.VOModel  I added 1 line to the if statement that checks if a property is to be ingored (around line 200):
      if (props[i].getReadMethod()!=null &&
                  props[i].getReadMethod().getParameterTypes().length==0 &&
                  ValueObject.class.isAssignableFrom( props[i].getReadMethod().getReturnType()) &&
                  form.getAttributeNamesToIgnore().contains(props[i].getName()) == false
              )

      mcarniel, would it be possible to add this slight modification to the framework?