Announcement Announcement Module
Collapse
No announcement yet.
LazyInitializationException in TimerTask Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • LazyInitializationException in TimerTask

    I have a Spring/Hibernate/JSP application and I have TimerTask that needs to
    use a hibernate class called 'GenericService'(This is name of the interface and as you will see in the code GenericHibernateService is the hibernate implementation of this interface).
    When I use the TimerTask outside of the spring context as a standalone java application (Either using a main method or JUnit) everything works FINE because I use the following to inject my dependency:
    ....
    SessionFactory sessionFactory = (SessionFactory) ctx.getBean("sessionFactory");
    Session s = sessionFactory.openSession();
    System.out.println("Session code" + s.hashCode());
    TransactionSynchronizationManager.bindResource(ses sionFactory, new SessionHolder(s));
    genericService = (GenericService)ctx.getBean("genericServiceTX");
    ....

    <bean id="genericService" class="....service.impl.GenericServiceHibernate">
    <property name="sessionFactory">
    <ref local="sessionFactory" />
    </property>
    </bean>

    <bean id="genericServiceTX" parent="baseTransactionProxy">
    <property name="target"><ref local="genericService"/></property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.Hibernat eTransactionManager">
    <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>

    <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean"
    abstract="true">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
    <props>
    <prop key="save*">PROPAGATION_REQUIRED</prop>
    <prop key="delete*">PROPAGATION_REQUIRED</prop>
    <prop key="update*">PROPAGATION_REQUIRED</prop>
    <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
    <prop key="iterate*">PROPAGATION_REQUIRED,readOnly</prop>
    </props>
    </property>
    </bean>


    However, if trying to use withing spring web application: org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed

    I would appreciate any help.

    Rex

  • #2
    Is it possible to see the code and configuration you are trying to use with the TimerTask? If you can wrap it in [code] [ /code] tags, it's soooo much easier to read!
    Last edited by karldmoore; Aug 29th, 2007, 12:02 PM.

    Comment


    • #3
      Inside of the Timer task I am just calling one the methods of the GenericService which makes a simple query to the database for past-due activities. Here is the code inside of the run method:

      Code:
      List activities = genericService.getPastDueActivities();
      		
      Iterator i = activities.iterator();
      		
      	while ( i.hasNext()) {
      			
      		Activity ac = (Activity)i.next();
      		String userEmailText = getEmailBody(ac, false);
      		String destinationEmailAddressUser = ac.getAssignedUser().getCommunication().getEmail();
      			sendEmail(destinationEmailAddressUser, userEmailText);
      			if (ac instanceof SalesActivity) {
      				SalesActivity sa = (SalesActivity)ac;
      				String managerEmailText = getEmailBody(ac, true);
      				String destinationEmailAddressManager = sa.getAssignedUser().getCommunication().getEmail();
      				sendEmail(destinationEmailAddressManager, managerEmailText);
      			} 			
      		}			
      
      
      
      
      Method "genericService.getPastDueActivities()" is just:
      public List getPastDueActivities() {
      
      		Date now = new Date();
      		String hql = "FROM Activity as a WHERE a.dueDate <?";
      		return getHibernateTemplate().find(hql, now);
      	}
      
      
      My spring bean configuration for the timer task is: 
      
          <bean id="pastDueActivityAlert" class="com.silicerayan.hydra.jobs.PastDueActivitiesEmailNotification"> 
      		<property name="genericService"><ref bean="genericServiceTX"/></property>
      	</bean> 
      
      	<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
      		<!-- wait 10 seconds before starting repeated execution -->
      		<property name="delay" value="1000" />
      		<!-- run every 50 seconds -->
      		<property name="period" value="50000" />
      		<property name="timerTask" ref="pastDueActivityAlert" />
      	</bean>
      	<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
      		<property name="scheduledTimerTasks">
      			<list>
      		        <ref bean="scheduledTask" />
      			</list>
      		</property>
      		
      	</bean>
      If you think its necessary I can send you all my relevant configuration as a new post with <code> tags. Thank you in advanced for the time.

      Rex

      Comment


      • #4
        The problem here is that the TimerTask is outside of the transaction. Once you've left the service the transaction will be closed and the Session along with it. You'd need to eagerly load the items to prevent the exception. There are lots of examples on here about it and in the hibernate reference manual.
        Last edited by karldmoore; Aug 29th, 2007, 12:02 PM.

        Comment


        • #5
          So how come when instead of injecting the service in XML I initialize my service in the constructor with the following code (Which works in some main method and JUnit), everything works fine?

          Code:
          .....
          SessionFactory sessionFactory = (SessionFactory) ctx.getBean("sessionFactory");
          Session s = sessionFactory.openSession();
          System.out.println("Session code" + s.hashCode());
          TransactionSynchronizationManager.bindResource(ses sionFactory, new SessionHolder(s));
          genericService = (GenericService)ctx.getBean("genericServiceTX");

          Comment


          • #6
            If you've already bound a Session then this is still open when you try and lazy load the items. It's the same as using the Spring test classes.
            http://www.springframework.org/docs/...tml#testing-tx
            Last edited by karldmoore; Aug 29th, 2007, 12:02 PM.

            Comment


            • #7
              Injecting dependency (genericService) is not working for the timertask and my service class is wrapped inside the transaction as shown below.
              Code:
               <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
                   abstract="true">
                 <property name="transactionManager" ref="transactionManager"/>
                 <property name="transactionAttributes">
                   <props>
                     <prop key="save*">PROPAGATION_REQUIRED</prop>
                     <prop key="delete*">PROPAGATION_REQUIRED</prop>		 
                     <prop key="update*">PROPAGATION_REQUIRED</prop>
                     <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
              	   <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                     <prop key="iterate*">PROPAGATION_REQUIRED,readOnly</prop>
                   </props>
                 </property>
               </bean>	
              	 <bean id="genericService" class="com.silicerayan.hydra.service.impl.GenericServiceHibernate">
              		<property name="sessionFactory">
              			<ref local="sessionFactory" />
              		</property>
              	</bean>
                 <bean id="genericServiceTX" parent="baseTransactionProxy">
                    <property name="target"><ref local="genericService"/></property>
                 </bean>	
              
              
              	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
              		<property name="sessionFactory"><ref local="sessionFactory"/></property>
              	</bean>
              (by the way, does the ordering of bean decleration matters?)



              My question is that why the following works with the a java main method:

              XML:
              Code:
              ....
                  <bean id="pastDueActivityAlert" class="com.silicerayan.hydra.jobs.PastDueActivitiesEmailNotification"> 
              		<property name="genericService"><ref bean="genericService"/></property>
              	</bean> 
              
              
                 <bean id="genericServiceTX" parent="baseTransactionProxy">
                    <property name="target"><ref local="genericService"/></property>
                 </bean>	
              
               <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
                   abstract="true">
                 <property name="transactionManager" ref="transactionManager"/>
                 <property name="transactionAttributes">
                   <props>
                     <prop key="save*">PROPAGATION_REQUIRED</prop>
                     <prop key="delete*">PROPAGATION_REQUIRED</prop>		 
                     <prop key="update*">PROPAGATION_REQUIRED</prop>
                     <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
              	   <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                     <prop key="iterate*">PROPAGATION_REQUIRED,readOnly</prop>
                   </props>
                 </property>
               </bean>
              
              	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
              		<property name="sessionFactory"><ref local="sessionFactory"/></property>
              	</bean>
              My java code:
              Code:
              public class PastDueActivitiesEmailNotification  extends TimerTask{ 
              
              ....
              	public PastDueActivitiesEmailNotification() {
              		
              		ApplicationContext ctx = new FileSystemXmlApplicationContext(PATH_CONTEXT);
              	    SessionFactory  sessionFactory = (SessionFactory) ctx.getBean("sessionFactory");
              	    Session s = sessionFactory.openSession();
              	    System.out.println("Session code" + s.hashCode());
              	    TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));
              	    genericService = (GenericService)ctx.getBean("genericServiceTX");
              	}
              
              
              
              public static void main(String[] args) {
              		
              PastDueActivitiesEmailNotification pd = new PastDueActivitiesEmailNotification();
              	pd.run();
              	}
              But the exact same configuration does not work in my web application (when run under tomcat). Any pointer or suggestions will be greatly appreciated. Please keep in mind that I have to lazy load my objects.
              Last edited by rexfeizi; Jun 19th, 2007, 04:22 AM.

              Comment


              • #8
                I'm still not sure exactly what you are trying to achieve here. If you are depploying this as a web app then I'd presume you are using something like ContextLoaderListener to load the applicationContext. You don't really want to then create a new applicationContext for every TimerTask you create. I would have thought it might be easier to inject in the transactionManager and instead use TransactionTemplate to provide the transaction. Otherwise just call into a transactional service.
                Last edited by karldmoore; Aug 29th, 2007, 12:02 PM.

                Comment

                Working...
                X