title: Initialize lazy collections
body: <p>I'm developing a Struts2 + Spring + Hibernate webapp and I need to initialize a lazy collection after retrieving an object or a collection of that object.</p>
  
  <p><strong>Use case</strong></p>
  
  <p>I have a <strong>team</strong> model with a relation eagerly loaded called <strong>employees</strong> (I think it's obvious that this is a collection). In turn, <strong>employee</strong> model has a lazy relation <strong>registry</strong> that I need just for some specific actions so I don't need at all to load it eagerly.</p>
  
  <p>Now. I call my <code>teamService</code> (injected to my Struts2 controller with Spring) in order to retrieve a specific <code>teamItem</code> which has already his collection <strong>employees</strong> loaded. Now it's time to load for each employee its registry relation.</p>
  
  <p>Using the <code>employeeService</code> (also this injected to my Struts2 controller with Spring) I call the <code>initializeCollections()</code> method of his DAO that should load the lazy collection calling</p>
  
  <pre><code>Hibernate.initialize(employee.getRegistry());
  </code></pre>
  
  <p>When I perform this action a <code>org.hibernate.LazyInitializationException: could not initialize proxy - no Session</code> exception is thrown.</p>
  
  <p><em>stack trace:</em></p>
  
  <pre><code>at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167) ~[hibernate-core-3.6.10.Final.jar:3.6.10.Final]
  at org.hibernate.Hibernate.initialize(Hibernate.java:414) ~[hibernate-core-3.6.10.Final.jar:3.6.10.Final]
  at web.bkgd.simba.dao.registry.RegistryEmployeeDAO.initializeCollections(RegistryEmployeeDAO.java:438) ~[RegistryEmployeeDAO.class:?]
  at web.bkgd.simba.service.abstractions.BaseService.initializeCollections(BaseService.java:142) ~[BaseService.class:?]
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_79]
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_79]
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_79]
  at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_79]
  at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
  at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
  at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
  at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
  at com.sun.proxy.$Proxy1302.initializeCollections(Unknown Source) ~[?:?]
  at web.bkgd.simba.controller.ajax.agenda.TeamController.doSomething(TeamController.java:177) ~[AjaxTeamController.class:?]
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_79]
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_79]
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_79]
  at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_79]
  at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:870) ~[ognl-3.0.6.jar:?]
  at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1293) ~[ognl-3.0.6.jar:?]
  at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68) ~[ognl-3.0.6.jar:?]
  at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:117) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:108) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1369) ~[ognl-3.0.6.jar:?]
  at ognl.ASTMethod.getValueBody(ASTMethod.java:90) ~[ognl-3.0.6.jar:?]
  at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[ognl-3.0.6.jar:?]
  at ognl.SimpleNode.getValue(SimpleNode.java:258) ~[ognl-3.0.6.jar:?]
  at ognl.Ognl.getValue(Ognl.java:494) ~[ognl-3.0.6.jar:?]
  at ognl.Ognl.getValue(Ognl.java:458) ~[ognl-3.0.6.jar:?]
  at com.opensymphony.xwork2.ognl.OgnlUtil$2.execute(OgnlUtil.java:309) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.ognl.OgnlUtil.compileAndExecute(OgnlUtil.java:340) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.ognl.OgnlUtil.getValue(OgnlUtil.java:307) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:423) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:287) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:250) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at web.bkgd.simba.utility.interceptors.SessionCleanInterceptor.intercept(SessionCleanInterceptor.java:86) ~[SessionCleanInterceptor.class:?]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.interceptor.DeprecationInterceptor.intercept(DeprecationInterceptor.java:41) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:167) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:76) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:125) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:253) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:139) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164) ~[struts2-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) ~[xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189) [xwork-core-2.3.24.1.jar:2.3.24.1]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.24.1.jar:2.3.24.1]
  at web.bkgd.simba.utility.interceptors.LoginInterceptor.intercept(LoginInterceptor.java:113) [LoginInterceptor.class:?]
  at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54) [struts2-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:564) [struts2-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81) [struts2-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99) [struts2-core-2.3.24.1.jar:2.3.24.1]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.61]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.61]
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.61]
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.61]
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) [catalina.jar:7.0.61]
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) [catalina.jar:7.0.61]
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [catalina.jar:7.0.61]
  at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [catalina.jar:7.0.61]
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.61]
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) [catalina.jar:7.0.61]
  at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) [tomcat-coyote.jar:7.0.61]
  at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620) [tomcat-coyote.jar:7.0.61]
  at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) [tomcat-coyote.jar:7.0.61]
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [?:1.7.0_79]
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [?:1.7.0_79]
  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.61]
  at java.lang.Thread.run(Thread.java:745) [?:1.7.0_79]
  </code></pre>
  
  <ul>
  <li>Am I doing something wrong?</li>
  <li>Is there a different way to load that lazy collection?</li>
  </ul>
  
  <p><strong>EDIT 01-12-2015</strong></p>
  
  <p>I've tried to follow <em>Predrag Maric</em> answer and I have a little edit to do since seems still not working.</p>
  
  <p>So:</p>
  
  <blockquote>
    <ol>
    <li>Implement Open Session in View pattern</li>
    </ol>
  </blockquote>
  
  <p>No way. This solution may cause a very deep loading of the relations expecially for JSON serialization. Of course I can always define the <code>&lt;param name="includeProperties"&gt;</code> tag and load just what I need, but I'm still a little scared of the performances.</p>
  
  <blockquote>
    <ol start="2">
    <li>Initialize whatever you need in the first service</li>
    </ol>
  </blockquote>
  
  <p>And here is the point. I've changed my action and DAO structure in order to implement this function. I've used a little of reflection in order to create a general method that I can use in every single DAO of my application.</p>
  
  <p>How it works is very simple:</p>
  
  <p><strong>Example</strong></p>
  
  <p>INPUT:</p>
  
  <ul>
  <li>beanClass: Team</li>
  <li>model: team with no relations loaded</li>
  <li>relations: List:{"relation", "relation.childRelation.grandChildRelation"}</li>
  </ul>
  
  <p>The method for the first string simply calls <code>Hibernate.initialize()</code> method and for the second one splits the string in order to load:</p>
  
  <ul>
  <li>realation, returns <code>initializeRelations(relation.class, relation, "childRelation.grandChildRelation");</code></li>
  <li>childRelation, returns <code>initializeRelations(childRelation.class, childRelation, "grandChildRelation");</code></li>
  <li>grandChildRelation;</li>
  </ul>
  
  <p>Here you have the code:</p>
  
  <p><strong>TEAM DAO</strong></p>
  
  <p>These methods are called after a team bean or a list of team beans has been loaded from the database</p>
  
  <pre><code>/**
   * Initialize relations. This method returns true if a correct
   * initialization of the relation has been made by hibernate, false in any
   * other case. If the relations object is a List, the method recursively
   * call himself in order to initialize every single instance of the list.
   * If the relations string contains a "." it means that a grandchild
   * relation has to be loaded.
   *
   * @param beanClass
   * @param model
   * @param relations
   * @return boolean
   */
  public boolean initializeRelations(Class beanClass, BaseModel model, Object relations) {
      // Check if relations is a List
      if (relations instanceof List) {
          // Recursively call initializeRelations
          for (String relation : (List&lt;String&gt;) relations) {
              return initializeRelations(beanClass, model, relation);
          }
      } else if (relations instanceof String) {
          // If relations contains "." then a grandChild relation has to be loaded.
          if (((String) relations).contains(".")) {
              String[] childRelations = ((String) relations).split("\\.");
  
              // Initialize the child relation
              Object newChildRelations = initializeRelation(beanClass, model, childRelations[0]);
  
              if (newChildRelations == null) {
                  return false;
              } else if (newChildRelations instanceof BaseModel) {
                  initializeRelations(newChildRelations.getClass(), model, (Object[]) Arrays.copyOfRange(childRelations, 1, childRelations.length));
              } else if (newChildRelations instanceof List) {
                  for (Object newChildRelation : childRelations) {
                      initializeRelations(newChildRelation.getClass(), model, (Object[]) Arrays.copyOfRange(childRelations, 1, childRelations.length));
                  }
              }
          } else {
              Object newChildRelations = initializeRelation(beanClass, model, (String) relations);
  
              return newChildRelations == null;
          }
      }
  
      return false;
  }
  
  private Object initializeRelation(Class beanClass, BaseModel model, String relation) {
      try {
          for (PropertyDescriptor pd : Introspector.getBeanInfo(beanClass).getPropertyDescriptors()) {
              if (pd.getReadMethod() != null &amp;&amp; !"class".equals(pd.getName()) &amp;&amp; relation.toLowerCase().equals(pd.getName().toLowerCase()) &amp;&amp; pd.getReadMethod().invoke(model) == null) {
                  Hibernate.initialize(pd.getReadMethod().invoke(model));
  
                  return pd.getReadMethod().invoke(model);
              }
          }
      } catch (IntrospectionException ex) {
          LOG.warn("Cannot initialize ralation", ex);
      } catch (HibernateException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
          LOG.warn("Cannot initialize ralation", ex);
      }
      return null;
  }
  </code></pre>
  
  <p>But what I see in my log is that just the first relation is loaded</p>
  
  <pre><code>[DEBUG] 01-12-2015 14:06:52 Controller - relation: Employee{data1="data1", data2="data2", data3="data3", data4="data4", data5="data5"}
  [DEBUG] 01-12-2015 14:06:52 Controller - child: [!!!model.Registry_$$_javassist_17@75ce9b7d=&gt;org.hibernate.LazyInitializationException:could not initialize proxy - no Session!!!]
  </code></pre>