Announcement Announcement Module
Collapse
No announcement yet.
Lazy fetching failure while using a bean with init method Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Lazy fetching failure while using a bean with init method

    Hello,

    I am using Spring Hibernate DAO support for my DAOS, and trying to initialize an object in the context, which uses such DAOS in the init-method. Although I am using an Hibernate Interceptor to avoid lazy fetching to fail in my unit tests and, it lokks like there is a problem while initializing my 'objectDefinitionSourceTarget' bean. The troublesome bean has a method that reads some values from the database.

    The problem only gets there as I use init-method for 'objectDefinitionSourceTarget'. I have started to suspect about my configuration, since I turned off lazy fetching and stared to get an OutofMemory Exception while retrieving a few rows.



    Here is my context:

    Code:
    <!-- DataSource Definition --> 
       <bean id="mydataSource" 
             class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
          <property name="driverClassName"> 
             <value>com.mysql.jdbc.Driver</value> 
          </property> 
          <property name="url"> 
             <value>jdbc&#58;mysql&#58;//jgarcia&#58;3306/seguridad</value> 
          </property> 
          <property name="username"> 
             <value>root</value> 
          </property> 
          <property name="password"> 
             <value>root</value> 
          </property> 
       </bean> 
        
       <!-- Spring Data Access Exception Translator Defintion --> 
       <bean id="jdbcExceptionTranslator" class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator"> 
          <property name="dataSource"><ref bean="mydataSource"/></property> 
       </bean> 
      
       <!-- Hibernate SessionFactory Definition --> 
       <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> 
          <property name="mappingResources"> 
                 <list> 
                <value>co/com/unionsoluciones/seguridad/modelo/bo/Usuario.hbm.xml</value>    
                <value>co/com/unionsoluciones/seguridad/modelo/bo/Url.hbm.xml</value>    
                <value>co/com/unionsoluciones/seguridad/modelo/bo/Rol.hbm.xml</value>    
                </list> 
          </property>    
          <property name="hibernateProperties"> 
             <props> 
                <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop> 
                <prop key="hibernate.show_sql">true</prop> 
                <prop key="hibernate.cglib.use_reflection_optimizer">true</prop> 
                <prop key="hibernate.cache.provider_class">net.sf.hibernate.cache.HashtableCacheProvider</prop> 
             </props> 
          </property>    
           
          <property name="dataSource"> 
             <ref bean="mydataSource"/> 
          </property> 
       </bean> 
        
          <!-- Hibernate Transaction Manager Definition --> 
       <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"> 
          <property name="sessionFactory"><ref local="sessionFactory"/></property> 
       </bean> 
      
      
        <!-- Hibernate Template Defintion --> 
       <bean id="hibernateTemplate" class="org.springframework.orm.hibernate.HibernateTemplate"> 
          <property name="sessionFactory"><ref bean="sessionFactory"/></property> 
          <property name="jdbcExceptionTranslator"><ref bean="jdbcExceptionTranslator"/></property> 
       </bean>     
    
       <!-- DAO's --> 
       <bean id="rolDao" class="co.com.unionsoluciones.seguridad.modelo.dao.hibernate.RolDaoHibernateImpl"> 
       <property name="hibernateTemplate"><ref bean="hibernateTemplate"/></property> 
       </bean> 
        
       <bean id="urlDao" class="co.com.unionsoluciones.seguridad.modelo.dao.hibernate.UrlDaoHibernateImpl"> 
       <property name="hibernateTemplate"><ref bean="hibernateTemplate"/></property> 
       </bean> 
        
       <bean id="usuarioDao" class="co.com.unionsoluciones.seguridad.modelo.dao.hibernate.UsuarioDaoHibernateImpl"> 
       <property name="hibernateTemplate"><ref bean="hibernateTemplate"/></property> 
       </bean> 
        
        
       <!--<bean id="memoryAuthenticationDao" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl"> 
           <property name="userMap"> 
               <value> 
                   user=pass,ROLE_USER,ROLE_SUPERVISOR 
                   user1=pass,ROLE_USER 
                   user2=pass,ROLE_USER 
               </value> 
           </property> 
       </bean>--> 
        
       <bean id="unionAuthenticationDao" class="co.com.unionsoluciones.seguridad.modelo.dao.UnionAthenticationDao"> 
            <property name="usuarioDao"> 
                <ref local="usuarioDao"/> 
            </property> 
       </bean> 
        
        
       <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"> 
            <property name="authenticationDao"> 
                <ref local="unionAuthenticationDao"/> 
            </property> 
       </bean> 
        
       <bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"> 
           <property name="providers"> 
               <list> 
                   <ref bean="daoAuthenticationProvider"/> 
               </list> 
           </property> 
       </bean> 
        
       <bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"> 
           <property name="authenticationManager"> 
               <ref bean="authenticationManager"/> 
           </property> 
           <property name="authenticationFailureUrl"> 
               <value>/login.jsp?error=1</value> 
           </property> 
           <property  name="defaultTargetUrl"> 
               <value>/</value> 
           </property> 
           <property name="filterProcessesUrl"> 
               <value>/j_acegi_security_check</value> 
           </property> 
       </bean> 
        
       <bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/> 
    
       <bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.UnanimousBased"> 
           <property name="allowIfAllAbstainDecisions"> 
               <value>false</value> 
           </property> 
           <property name="decisionVoters"> 
               <list> 
                  <ref local="roleVoter"/> 
               </list> 
           </property> 
       </bean> 
    
       <bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"> 
           <property name="filterSecurityInterceptor"> 
               <ref bean="filterInvocationInterceptor"/> 
           </property> 
           <property name="authenticationEntryPoint"> 
               <ref bean="authenticationEntryPoint"/> 
           </property> 
       </bean> 
    
       <bean id="httpSessionIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter"> 
       <property name="context"><value>net.sf.acegisecurity.context.security.SecureContextImpl</value></property> 
       </bean> 
        
       <bean id="authenticationEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"> 
           <property name="loginFormUrl"> 
               <value>/login.jsp</value> 
           </property> 
       </bean> 
        
       <bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor"> 
           <property name="authenticationManager"> 
               <ref bean="authenticationManager"/></property> 
           <property name="accessDecisionManager"> 
               <ref bean="accessDecisionManager"/></property> 
           <property name="objectDefinitionSource"> 
            <value> 
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON 
               PATTERN_TYPE_APACHE_ANT 
                /secure/super/**=ROLE_SUPERVISOR 
                /secure/**=ROLE_USER,ROLE_SUPERVISOR 
            </value> 
           </property> 
       </bean> 
        
        
    
       <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor"> 
             <property name="sessionFactory"> 
               <ref bean="sessionFactory"/> 
             </property> 
        </bean> 
        
        <bean id="objectDefinitionSourceTarget" class="co.com.unionsoluciones.seguridad.modelo.bo.PathBasedFilterInvocationDefinitionMapUnion" 
          init-method="init"> 
       <property name="urlDao"> 
          <ref bean="urlDao"/> 
       </property> 
       </bean> 
        
         <bean id="objectDefinitionSource" class="org.springframework.aop.framework.ProxyFactoryBean"> 
             <property name="target"><ref bean="objectDefinitionSourceTarget"/></property> 
             <property name="proxyInterfaces"> 
               <value>net.sf.acegisecurity.intercept.ObjectDefinitionSource</value> 
             </property> 
             <property name="interceptorNames"> 
               <list> 
                  <value>hibernateInterceptor</value> 
               </list> 
             </property> 
         </bean>
    The error, while loading the context is

    [junit] Testcase: testActualizar(co.com.unionsoluciones.seguridad.mo delo.dao.TestUrlDao): Caused an ERROR
    [junit] Error creating bean with name 'objectDefinitionSourceTarget' defined in class path resource [securityContext.xml]: Initialization of bean failed; nested exception is net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no session or session was closed
    [junit] org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'objectDefinitionSourceTarget' defined in class path resource [securityContext.xml]: Initialization of bean failed; nested exception is net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no session or session was closed
    [junit] net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no session or session was closed
    Notice the init method in the troublesome bean is as follows (it uses beans from the AppContext)

    Code:
    public void init&#40;&#41;&#123; 
          List urls = this.urlDao.obtenerTodosUrls&#40;&#41;; 
           
          while &#40;urls.listIterator&#40;&#41;.hasNext&#40;&#41;&#41; &#123; 
             Url url = &#40;Url&#41; urls.listIterator&#40;&#41;.next&#40;&#41;; 
             String urlPath = url.getUrl&#40;&#41;; 
              
              
             Set rols = url.getRols&#40;&#41;; 
             ConfigAttributeDefinition configAttributeDefinition = new ConfigAttributeDefinition&#40;&#41;; 
              
             while &#40;rols.iterator&#40;&#41;.hasNext&#40;&#41;&#41; &#123; 
                Rol rol = &#40;Rol&#41; rols.iterator&#40;&#41;.next&#40;&#41;; 
                configAttributeDefinition.addConfigAttribute&#40;new SecurityConfig&#40;rol.getSpringRole&#40;&#41;&#41;&#41;; 
             &#125; 
             this.addSecureUrl&#40;urlPath, configAttributeDefinition&#41;; 
          &#125; 
    
       &#125;
    Please help! I am stuck and in a hurry....

    Julian


    pd: same post is here http://forum.springframework.org/viewtopic.php?t=5737, buit i changed the topic's category since this is more suitable i guess. Please post here.

  • #2
    It's an interesting problem.

    In your case you aparently didn't decorate your target bean (objectDefinitionSourceTarget) with a transactional interceptor. But it doesn't matter because the problem would remain.

    What happens is this: the application context calls the init method which calls the DAO which calls HibernateTemplate which will create a Hibernate session to execute your query and close it immediately.

    If this would be any method and you would have a transactional interceptor in place the problem would not occur since the Hibernate session would remain available in the scope of each method call on your target bean. However, since the application context calls the init method on the target bean and not through a proxy the transaction manager is out of the loop.

    A work-around would be to move the code in you init method to another bean, demarcate that method transactionally through a proxy and call that proxy from your init method.

    I'm not sure if there are alternative solutions for this problem.

    Comment


    • #3
      Maybe try moving what you do in init() to a BeanPostPrococessor, which can be configured and proxied like any other bean.

      Comment


      • #4
        Desperate

        I have tried tentacle's solution, but got this error:
        org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'objectDefinitionSource' defined in class path resource [securityContext.xml]: Initialization of bean failed; nested exception is java.lang.OutOfMemoryError: null
        java.lang.OutOfMemoryError
        I am not sure why, cos as I mentioned already, there are but a very few rows to be retrieved, and that should work even without lazy fetching.

        Maybe there's somethig wrong in my context configuration. With the changes suggested by tentacle the part I have changed in my appContex looks like this:

        Code:
         <bean id="objectDefinitionSource" class="co.com.unionsoluciones.seguridad.modelo.bo.PathBasedFilterInvocationDefinitionMapUnion" init-method="init">
        	<property name="urlDao">
        		<ref local="urlDao"/>
        	</property>
        	<property name="initExecutor">
        		<ref local="initExecutor"/> 
        	</property>
        	</bean>
        	
        	  
        	<bean id="initExecutorTarget" class="co.com.unionsoluciones.seguridad.modelo.bo.utils.InitExcecutor">
        	<property name="urlDao"> 
        		<ref local="urlDao"/>
        	</property>
        	<property name="mapUnion">
        		<ref local="objectDefinitionSource"/>
        	</property>
        	
        	</bean>
        	  
        	  
        	  <!-- Bean initExecutorProxy Proxy -->
        	<bean id="initExecutor" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        		<property name="transactionManager"><ref local="transactionManager"/></property>
        		<property name="target"><ref local="initExecutorTarget"/></property>
        		<property name="transactionAttributes">
        		<props>
        		<prop key="init*">PROPAGATION_REQUIRED, -Exception</prop>
        		</props>
        		</property>
        	</bean>
        My initexecutor (the new class) looks like
        Code:
        public class InitExcecutor &#123;
        
        	/**
        	 * @return Returns the mapUnion.
        	 */
        	public PathBasedFilterInvocationDefinitionMapUnion getMapUnion&#40;&#41; &#123;
        		return mapUnion;
        	&#125;
        	/**
        	 * @param mapUnion The mapUnion to set.
        	 */
        	public void setMapUnion&#40;PathBasedFilterInvocationDefinitionMapUnion mapUnion&#41; &#123;
        		this.mapUnion = mapUnion;
        	&#125;
        	/**
        	 * @return Returns the urlDao.
        	 */
        	public UrlDao getUrlDao&#40;&#41; &#123;
        		return urlDao;
        	&#125;
        	/**
        	 * @param urlDao The urlDao to set.
        	 */
        	public void setUrlDao&#40;UrlDao urlDao&#41; &#123;
        		this.urlDao = urlDao;
        	&#125;
        	UrlDao urlDao;
        	PathBasedFilterInvocationDefinitionMapUnion mapUnion;
        	/**
        	 * 
        	 */
        	public InitExcecutor&#40;&#41; &#123;
        		super&#40;&#41;;
        		// TODO Auto-generated constructor stub
        	&#125;
        	public void init&#40;&#41;&#123;
        //		Obtiene las urls desde la base de datos
        		List urls = this.urlDao.obtenerTodosUrls&#40;&#41;;
        		
        		//Para cada url aņade url seguras
        		while &#40;urls.listIterator&#40;&#41;.hasNext&#40;&#41;&#41; &#123;
        			Url url = &#40;Url&#41; urls.listIterator&#40;&#41;.next&#40;&#41;;
        			String urlPath = url.getUrl&#40;&#41;;
        			
        			
        			// para cada rol correspondiente a la url crea un secutiryContex y lo aņande
        			//a el configAttributeDefinition corrspondiente al url 
        			Set rols = url.getRols&#40;&#41;;
        			ConfigAttributeDefinition configAttributeDefinition = new ConfigAttributeDefinition&#40;&#41;;
        			
        			while &#40;rols.iterator&#40;&#41;.hasNext&#40;&#41;&#41; &#123;
        				Rol rol = &#40;Rol&#41; rols.iterator&#40;&#41;.next&#40;&#41;;
        				configAttributeDefinition.addConfigAttribute&#40;new SecurityConfig&#40;rol.getSpringRole&#40;&#41;&#41;&#41;;
        			&#125;
        			mapUnion.addSecureUrl&#40;urlPath, configAttributeDefinition&#41;;
        		&#125;
        	&#125;
        
        &#125;
        And my original init in class PathBasedFilterInvocationDefinitionMap has been reduced to:

        Code:
        public void init&#40;&#41;&#123;
        	this.initExecutor.init&#40;&#41;;
        	&#125;
        I am not sure why is it running out of memory :S.

        Please HELP!

        I wonder if the approach using a BeanPostProcessor might help. Is there any example with this working? Do you guys think this may help avoid running out of memory?

        Comment


        • #5
          The error I am getting is

          org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'objectDefinitionSource' defined in class path resource [securityContext.xml]: Initialization of bean failed; nested exception is java.lang.OutOfMemoryError: null
          java.lang.OutOfMemoryError
          Last couple of lines I see at console:

          INFO: JDBC 3.0 Savepoint class is available
          Hibernate: select this.Id_URL as Id_URL0_, this.URL as URL0_, this.Descripcion_URL as Descripc3_0_ from url this where 1=1
          Hibernate: select rols0_.id_url as id_url__, rols0_.nombre_rol as nombre_rol__, rol1_.nombre_rol as nombre_rol0_, rol1_.descripcion_rol as descripc2_0_ from url_rol rols0_ inner join rol rol1_ on rols0_.nombre_rol=rol1_.nombre_rol where rols0_.id_url=?
          26-may-2005 17:43:58 org.springframework.beans.factory.support.Abstract BeanFactory destroySingletons
          INFO: Destroying singletons in factory {org.springframework.beans.factory.support.Default ListableBeanFactory defining beans [mydataSource,jdbcExceptionTranslator,sessionFactor y,transactionManager,hibernateTemplate,rolDao,urlD ao,usuarioDao,unionAuthenticationDao,daoAuthentica tionProvider,authenticationManager,authenticationP rocessingFilter,roleVoter,accessDecisionManager,se curityEnforcementFilter,httpSessionIntegrationFilt er,authenticationEntryPoint,filterInvocationInterc eptor,objectDefinitionSource,initExecutorTarget,in itExecutor]; root of BeanFactory hierarchy}
          26-may-2005 17:43:58 org.springframework.orm.hibernate.LocalSessionFact oryBean destroy
          INFO: Closing Hibernate SessionFactory
          26-may-2005 17:43:58 net.sf.hibernate.impl.SessionFactoryImpl close
          INFO: closing

          Comment

          Working...
          X