Announcement Announcement Module
Collapse
No announcement yet.
TimerFactoryBean and more than one tasks problem Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • TimerFactoryBean and more than one tasks problem

    Hi

    Scenario:
    My use-case requires me to setup two Tasks after server startup.
    Task A (scheduledTaskEDI) will loop forever and listen on an AS/400 dataqueue and process any incomming messages.
    Task B (scheduledTaskTilmeldKunde) will do the same as A but listening to a different data queue.

    I am using the build Spring support to setup my tasks and active the tasks after server startup using the TimerFactoryBean.

    The problems is:
    My 2nd task is never setup since the first task is never terminated (loop forever).

    My configuration is:
    Code:
    	<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
    		<property name="daemon">
    			<value>false</value>
    		</property>
    		<property name="scheduledTimerTasks">
    			<list>
    				<ref local="scheduledTaskTilmeldKunde"/>
    				<ref local="scheduledTaskEDI"/>
    			</list>
    		</property>
    	</bean>
    
    	<bean id="scheduledTaskTilmeldKunde" class="org.springframework.scheduling.timer.ScheduledTimerTask">
    		<property name="delay">
    			<value>10000</value>
    		</property>
    		<property name="period">
    			<value>-1</value>
    		</property>
    		<property name="timerTask">
    			<ref local="checkTilmeldKunde"/>
    		</property>
    	</bean>
    
    	<bean id="checkTilmeldKunde" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
    		<property name="targetObject">
    			<ref local="as400DataQueueTilmeldKunde"/>
    		</property>
    		<property name="targetMethod">
    			<value>listen</value>
    		</property>
    	</bean>
    
    	<bean id="checkFakturaEDI" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
    		<property name="targetObject">
    			<ref local="as400DataQueueEDI"/>
    		</property>
    		<property name="targetMethod">
    			<value>listen</value>
    		</property>
    	</bean>
    
    	<bean id="scheduledTaskEDI" class="org.springframework.scheduling.timer.ScheduledTimerTask">
    		<property name="delay">
    			<value>5000</value>
    		</property>
    		<property name="period">
    			<value>-1</value>
    		</property>
    		<property name="timerTask">
    			<ref local="checkFakturaEDI"/>
    		</property>
    	</bean>
    And from my Tomcat log it can see that only the first job is started.

    Code:
    Thread-2 12 jan 2005 10&#58;01&#58;24 INFO  dk.webfragt.access.as400.AS400DataQueueListener - DataQueueListener starting &#91;EDI&#93;
    Thread-2 12 jan 2005 10&#58;01&#58;25 DEBUG dk.webfragt.access.as400.AS400DataQueueListener - Got AS/400 system
    Thread-2 12 jan 2005 10&#58;01&#58;25 DEBUG dk.webfragt.access.as400.AS400DataQueueListener - Listening on data queue /QSYS.LIB/L2950TPGM.LIB/EBUDTAQ1.DTAQ, count=1

    I have tried setting the deamon property of TimerFactoryBean to both true or false. But it never works.

    If I change my code to terminate in the task instead of looping forever. Both jobs are started as the log below profs:

    Code:
    Thread-2 12 jan 2005 10&#58;09&#58;58 INFO  dk.webfragt.access.as400.AS400DataQueueListener - DataQueueListener starting &#91;EDI&#93;
    Thread-2 12 jan 2005 10&#58;10&#58;03 INFO  dk.webfragt.access.as400.AS400DataQueueListener - DataQueueListener starting &#91;TilmeldKunde&#93;

    I can see from the log above that both tasks are using the same thread Thread-2, but it could be the fact that the first job has terminated and thus Thread-2 is avail.

    So what do you do to make sure that my 2 tasks are using their own thread?

  • #2
    Okay I got it to work

    I changed from using the Spring MethodInvokingTimerTaskFactoryBean to my own TimerTask object that spawns a new Thread.
    Code:
    public class AS400DataQueueListenerTimerTask extends TimerTask &#123;
    
    	public AS400DataQueueListener listener;
    	
    	public void setListener&#40;AS400DataQueueListener listener&#41; &#123;
    		this.listener = listener;
    	&#125;
    	
    	public void run&#40;&#41; &#123;
    		Job job = new Job&#40;listener&#41;;
    		new Thread&#40;job&#41;.start&#40;&#41;;
    	&#125;
    	
    	/**
    	 * To start the listener in its own thread.
    	 */
    	class Job implements Runnable &#123;
    
    		private AS400DataQueueListener listener;
    		
    		public Job&#40;AS400DataQueueListener listener&#41; &#123;
    			this.listener = listener;
    		&#125;
    		
    		public void run&#40;&#41; &#123;
    			listener.listen&#40;&#41;;
    		&#125;
    		
    	&#125;
    
    &#125;
    Using this my two Tasks are started in their own thread, as the log shows:
    Code:
    Thread-14 12 jan 2005 10&#58;39&#58;27 INFO  dk.webfragt.access.as400.AS400DataQueueListener - DataQueueListener starting &#91;EDI&#93;
    Thread-14 12 jan 2005 10&#58;39&#58;27 DEBUG dk.webfragt.access.as400.AS400DataQueueListener - Got AS/400 system
    Thread-14 12 jan 2005 10&#58;39&#58;27 DEBUG dk.webfragt.access.as400.AS400DataQueueListener - Listening on data queue /QSYS.LIB/L2950TPGM.LIB/EBUDTAQ1.DTAQ, count=1
    Thread-15 12 jan 2005 10&#58;39&#58;32 INFO  dk.webfragt.access.as400.AS400DataQueueListener - DataQueueListener starting &#91;TilmeldKunde&#93;
    Thread-15 12 jan 2005 10&#58;39&#58;32 DEBUG dk.webfragt.access.as400.AS400DataQueueListener - Got AS/400 system
    Thread-15 12 jan 2005 10&#58;39&#58;32 DEBUG dk.webfragt.access.as400.AS400DataQueueListener - Listening on data queue /QSYS.LIB/L2950TPGM.LIB/EBUDTAQ2.DTAQ, count=1
    I would like to know if Spring actually have support for spawning a thread for the job to be executed?

    Comment


    • #3
      Originally posted by davsclaus
      I would like to know if Spring actually have support for spawning a thread for the job to be executed?
      Actually this problem arises from the Java Timer class used by Spring. This is from the documentation of java.util.Timer:

      Code:
      Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially. Timer tasks should complete quickly. If a timer task takes excessive time to complete, it "hogs" the timer's task execution thread.
      So for your case I would suggest using a quartz-based timer.

      Regards,
      Andreas

      Comment


      • #4
        Thanks Andreas

        I missed the part in the JDK javadoc - thanks.


        I thought about changing to Quartz also but the JDK timer is very simple and I only needed the new features that Juergen added to the comming Spring 1.1.4 to set period = -1 to make it a one-shot-task instead of repeated execution. I recon that Quartz also have a feature to fire the job only once.

        Comment


        • #5
          Yes it works nicely with Quartz instead. Now I can avoid having my TimerTask classes that spawns their own new Thread.

          For a one-shot execution job set both repeatCount and repeatInterval to 0.
          Code:
          	<bean id="ediTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
          		<property name="jobDetail">
          			<ref local="checkFakturaEDITask" />
          		</property>
          		<property name="startDelay">
          			<!-- 10 seconds -->
          			<value>10000</value>
          		</property>
          		<property name="repeatInterval">
          			<value>0</value>
          		</property>
          		<property name="repeatCount">
          			<value>0</value>
          		</property>
          	</bean>

          Comment

          Working...
          X