Announcement Announcement Module
Collapse
No announcement yet.
Spring(version 2.5)+ Quartz - SchedulerFactoryBean - waitForJobsToCompleteOnShutdown Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring(version 2.5)+ Quartz - SchedulerFactoryBean - waitForJobsToCompleteOnShutdown

    Hi,

    As per the documentation of property "waitForJobsToCompleteOnShutdown" within "org.springframework.scheduling.quartz.SchedulerFa ctoryBean", Spring should wait for running jobs to complete before shutdown.

    I have configured the scheduler in spring configuration xml as shown below -

    Code:
    <bean id="evaluatorPollerScheduler"
    		class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    		<property name="jobFactory">
    			<bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />
    		</property>
    		<property name="quartzProperties">
    			<props>
    				<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
    				<prop key="org.quartz.threadPool.threadCount">${scheduler.evaluator.thread.count}</prop>
    			</props>
    		</property>
    		<property name="waitForJobsToCompleteOnShutdown" value="true" />
    	</bean>

    I also have configured correponding trigger and job. Then I am scheduling the job using the scheduler.

    This Spring module is deployed on weblogic 8.1.

    When a 'shutdown' is issued from weblogic, it appears that weblogic does not wait for the spring job to complete before shutdown even though 'waitForJobsToCompleteOnShutdown' is set to TRUE.

    Could you please advice what could be wrong?

    Please let me know if you need any more details.

    Regards,
    Jacob

  • #2
    Shutdown on weblogic isn't the same as shutdown for an applicationcontext. It will only work if the context is closed nicely... If WebLogic choses not to wait for all applications before actually shutting down this property isn't going to help you.

    Comment


    • #3
      Hi Marten,

      Weblogic is issuing graceful shutdown command....so ideally it should wait for all currently running jobs to complete before shutdown.
      The class extending "ContextLoaderListener" configured as listener in web deployment descriptor (web.xml) is given below. Do I need to do anything more in the "contextDestroyed" method to ensure that context is nicely closed? -

      Code:
      package com.test.proview.notificationengine.servlet;
      
      import javax.servlet.ServletContextEvent;
      
      import org.apache.log4j.Logger;
      import org.springframework.web.context.ContextLoader;
      import org.springframework.web.context.ContextLoaderListener;
      import org.springframework.web.context.WebApplicationContext;
      
      import com.test.proview.notificationengine.scheduler.NotificationScheduleManager;
      import com.test.proview.notificationengine.util.NotificationEngineConstants;
      
      /**
       * Listener which initializes Spring context. Also triggers the quartz job scheduling.
       * 
       *  
       */
      public class SpringInitListener extends ContextLoaderListener
      {
          private static final Logger logger     =
                                                     Logger
                                                         .getLogger(NotificationEngineConstants.NOTIFICATIONENGINE_LOG_APPENDER);
      
          private static final String CLASS_NAME = SpringInitListener.class.getName();
      
          private ContextLoader       contextLoader;
      
          /*
           * (non-Javadoc)
           * 
           * @see org.springframework.web.context.ContextLoaderListener#contextInitialized(javax.servlet.ServletContextEvent)
           */
          public void contextInitialized(ServletContextEvent event)
          {
              final String METHOD_NAME = " | contextInitialized | ";
              logger.info(CLASS_NAME + METHOD_NAME
                  + NotificationEngineConstants.STARTS);
      
              this.contextLoader = createContextLoader();
              WebApplicationContext context =
                  this.contextLoader.initWebApplicationContext(event
                      .getServletContext());
      
              logger.debug(CLASS_NAME + METHOD_NAME
                  + "contextInitialized successfully");
      
              NotificationScheduleManager manager =
                  (NotificationScheduleManager) context
                      .getBean(NotificationEngineConstants.SCHEDULER_MANAGER_BEAN);
              manager.scheduleNewJob(null,
                  NotificationEngineConstants.EVALUATOR_POLLER_NAME, null,
                  NotificationEngineConstants.DIGEST_POLLER_NAME, null,
                  NotificationEngineConstants.PENDING_POLLER_NAME, null,
                  NotificationEngineConstants.REGULAR_POLLER_NAME);
      
              logger.debug(CLASS_NAME + METHOD_NAME
                  + "scheduleNewJob executed succesfully");
      
              logger
                  .info(CLASS_NAME + METHOD_NAME + NotificationEngineConstants.ENDS);
      
          }
      
          /*
           * (non-Javadoc)
           * 
           * @see org.springframework.web.context.ContextLoaderListener#createContextLoader()
           */
          protected ContextLoader createContextLoader()
          {
              return new ContextLoader();
          }
      
          /*
           * (non-Javadoc)
           * 
           * @see org.springframework.web.context.ContextLoaderListener#getContextLoader()
           */
          public ContextLoader getContextLoader()
          {
              return this.contextLoader;
          }
      
          /*
           * (non-Javadoc)
           * 
           * @see org.springframework.web.context.ContextLoaderListener#contextDestroyed(javax.servlet.ServletContextEvent)
           */
          public void contextDestroyed(ServletContextEvent event)
          {
                   
              if (this.contextLoader != null){
                  
                  this.contextLoader.closeWebApplicationContext(event
                      .getServletContext());
              }
          }
      }

      Comment


      • #4
        Why this class?! What is wrong with springs default... Your current implementation breaks some of spring functionality...

        I would implement it different and leave the default behavior as is.

        Code:
        package com.test.proview.notificationengine.servlet;
        
        import javax.servlet.ServletContextEvent;
        
        import org.apache.log4j.Logger;
        
        import com.test.proview.notificationengine.scheduler.NotificationScheduleManager;
        import com.test.proview.notificationengine.util.NotificationEngineConstants;
        
        /**
         * Listener which initializes Spring context. Also triggers the quartz job scheduling.
         * 
         *  
         */
        public class SpringInitListener extends ContextLoaderListener
        {
            private static final Logger logger     =
                                                       Logger
                                                           .getLogger(NotificationEngineConstants.NOTIFICATIONENGINE_LOG_APPENDER);
        
            private static final String CLASS_NAME = SpringInitListener.class.getName();
        
            /*
             * (non-Javadoc)
             * 
             * @see org.springframework.web.context.ContextLoaderListener#contextInitialized(javax.servlet.ServletContextEvent)
             */
            public void contextInitialized(ServletContextEvent event)
            {
                final String METHOD_NAME = " | contextInitialized | ";
                logger.info(CLASS_NAME + METHOD_NAME + NotificationEngineConstants.STARTS);
                logger.debug(CLASS_NAME + METHOD_NAME + "contextInitialized successfully");
        
                NotificationScheduleManager manager = getCurrentWebApplicationContext().getBean(NotificationEngineConstants.SCHEDULER_MANAGER_BEAN);
                manager.scheduleNewJob(null,
                    NotificationEngineConstants.EVALUATOR_POLLER_NAME, null,
                    NotificationEngineConstants.DIGEST_POLLER_NAME, null,
                    NotificationEngineConstants.PENDING_POLLER_NAME, null,
                    NotificationEngineConstants.REGULAR_POLLER_NAME);
        
                logger.debug(CLASS_NAME + METHOD_NAME + "scheduleNewJob executed succesfully");
                logger.info(CLASS_NAME + METHOD_NAME + NotificationEngineConstants.ENDS);
        
            }
        
        }
        Something like this. I would probably move the code in this class to a class implementing ApplicationListener and listen for ContextRefreshed/ContextStarted events to register this, leaving springs default intact.

        Also as you are running in a container you should use the container to manage your thread(pools) currently your configuration leads to creation of threads which the server knows nothing about.

        Code:
        <bean id="evaluatorPollerScheduler"
        	class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        	<property name="jobFactory">
        		<bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />
        	</property>
        	<property name="quartzProperties">
        		<props>
        			<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
        			<prop key="org.quartz.threadPool.threadCount">${scheduler.evaluator.thread.count}</prop>
        		</props>
        	</property>
        	<property name="waitForJobsToCompleteOnShutdown" value="true" />
        </bean>
        Instead of configuring quartz this way use Spring to configure an appropriate Executor for your environment and inject that into the SchedulerFactoryBean. (You probably need to setup the WorkManagerTaskExecutor for this).

        Code:
        <bean id="taskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor" >
        	<property name="workmanagerName" value="jndi_name_for_workmanager_under_weblogic" />
        </bean>
        
        <bean id="evaluatorPollerScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        	<property name="jobFactory">
        		<bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />
        	</property>
        	<property name="waitForJobsToCompleteOnShutdown" value="true" />
        	<property name="taskExecutor" ref="taskExecutor" />
        </bean>
        Last edited by Marten Deinum; Mar 18th, 2013, 06:03 AM.

        Comment

        Working...
        X