Spring Task Executor Scheduled too many instances of the task - java

I have a simple Spring Scheduled Taks defined by the following:
<context:component-scan base-package="com/test"/>
<task:scheduled-tasks>
<task:scheduled ref="myScheduler" method="doMyTask" fixed-rate="300000"/>
</task:scheduled-tasks>
<task:scheduler id="taskScheduler" pool-size="1"/>
<task:executor id="executorWithPoolSizeRange"
pool-size="1"
queue-capacity="100"/>
<bean id="cleanupClass" class="com.test.CleanupClass">
<property name="myProperty" value="3600"/>
</bean>
I would like to run a single thread synchronously every 5 minutes. However, what I get is FIVE instances of the task running consecutively every 5 minutes. Does anyone know if there is something missing from the XML description above?
I got the behavior I wanted using the #Scheduled annotations but I would rather not use annotation for the fixed-rate as I want it to be configurable outside of the code.
Thanks.

the following worked for me:
<bean id="task" class="com.foo.MyTask">
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="task" method="run" fixed-delay="300000" />
</task:scheduled-tasks>
<task:scheduler id="scheduler" pool-size="10" />
Greetings,
Mark

Is this the behavior you are seeing in the STS when you deploy it to tomcat? If so, you would want to undeploy the application, redeploy it and restart the application.

Another idea is to use SPEL expression from a properties file to use it with #Sched annotation. In that way it is still configurable while using that annotation.

Related

Spring Implementation - Recurring Timer

I have seen various thread on timertask issues. However I would like some clarification on the inner working on spring Scheduler APIs (3.1).
I have a requirement to kick off a timer every 10 secs. The application runs in clustered websphere zos. (atleast 4 jvm nodes).
Here is the wiring.
<bean id="dataProcessSchedulerTask" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
<property name="targetObject" ref="ondataTransferTimerWakeupService" />
<property name="targetMethod" value="processDataFeedMetadata" />
</bean>
<bean id="DATA_PROCESS_TIMER"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" ref="DATAProcessSchedulerTask" />
<property name="delay" value="#{systemProperties.DATA_PROCESS_TIMER}" />
<property name="period" value="#{systemProperties.DATA_PROCESS_TIMER}" />
</bean>
<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
list>
<ref bean="DATA_PROCESS_TIMER" />
</list>
</property>
</bean>
<bean id="onDATATransferTimerWakeupService" class="com.serviceimpl.OnDATATransferTimerWakeupService" />
I have defined (#async) for processDataFeedMetadata method.
The problem I am seeing the timer which fires every 10 secs correctly to begin with (4 jvms - 24 timer occurrences every min), started misbehaving after few hours (2 or 3 jvms stop firing any timer at all - 6 to 12 timer occurrences every min). I understand timertask implementation has it's own limitation. However, if I invoke an ASYNC method from MethodInvokingTimerTaskFactoryBean, Why would the timertask misbehave as
(1) timer should complete well within the interval as soon as it invokes ASYNC method.
(2) I don't see any exception from app logs and MethodInvokingTimerTaskFactoryBean should have handled and consume any exception if there are any.
Really appreciate if anyone has input on what is going on here ?
I suggest you utilizing Quartz Scheduler for Spring Scheduler implementation
http://quartz-scheduler.org/
Do you have this problem with 1 jvm ?

Can we create multiple instances of a same java(spring) batch job?

I am using quartz to schedule a spring batch job.
The job reads a file from a folder( which has multiple files ) does some processing and copies it to another folder.
is it possible to create multiple instances of the job, that will run concurrenty,reading multiple files ?
My question is :
In spring batch, is it possible to spawn multiple instances of the same job? I am using quartz schedular ?
In Spring Batch it is possible to start several jobs, provided you have supplied different JobParameters for each jobLauncher.run() call. jobLauncher in your Spring configuration will spawn each job in a separate thread, if it is configured with appropriate task executor:
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor" ref="taskExecutor" />
</bean>
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"
p:corePoolSize="5"
p:maxPoolSize="30" />
It is possible with Quartz, using a MethodInvokingJobDetailFactoryBean, for instance:
<bean id="myjob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<ref bean="someBean" />
</property>
<property name="targetMethod" value="someMethod" />
<!-- The concurrent property is already true by default
<property name="concurrent" value="true" />
-->
</bean>
Citing the Spring documentation
By default, Quartz Jobs are stateless, resulting in the possibility of jobs interfering with each other. If you specify two triggers for the same JobDetail, it might be possible that before the first job has finished, the second one will start. If JobDetail classes implement the Stateful interface, this won't happen. The second job will not start before the first one has finished. To make jobs resulting from the MethodInvokingJobDetailFactoryBean non-concurrent, set the concurrent flag to false.

Cron expression to run job once on application sturtup

I'm using org.springframework.scheduling.quartz.CronTriggerBean for trigger job.
Could you propose cron expression to trigger job execution only once on application startup pls?
I believe the actual answer is: no, you can't.
What you could do however when using Spring 3.1 (which is Milestone 2 at the time of writing) is create profiles which can be enabled for different environments. So you can use different beans and bean configurations depending on profiles you enable.
Instead of using scheduling, I would prefer to invoke your trigger via defining an init-method in your spring configuration
To run a job only once at startup with the Spring Quartz scheduler you can use the org.springframework.scheduling.quartz.SimpleTriggerBean which doesn't take a cronExpression but a startDelay and a repeatCount. Set the repeatCount to 0 for a single execution (see Quartz documentation on SimpleTrigger for further options).
<bean id="doJobOnceOnStartupTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="myJobDetail" />
<property name="startDelay" value="5000" />
<property name="repeatCount" value="0" />
</bean>
<bean id="myJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myBean" />
<property name="targetMethod" value="myMethod" />
</bean>
Additional information can be found int the
spring documentation: Chapter 22. Scheduling jobs using Quartz or Timer
You can use a SimpleTriggerBean - with a cron expression, you won't achieve this

Transaction Manager don't assume the transaction

i'm facing a problem i really dunno how to catch the cat tail (if you hollow me the joke :o))
i have a webapp in war, deploy in tomcat. the war contains 4 Jars.
4 jars have 4 applicationContext, with 4 entityManager, and 4 TransactionManager.
declare like this (change the number 1..):
<bean id="entityManagerFactory1"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource1"
p:persistence-unit-name="com.xxxxxx.domain" >
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:databasePlatform="${ds1.dbdialect}" p:generate-ddl="false"
p:showSql="${ds1.showsql}" />
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<bean id="transactionManager1" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory1">
depends-on="entityManagerFactory1" name="transactionManager1"/>
<tx:annotation-driven transaction-manager="transactionManager1" />
the context is load like this :
my problem i discover that when i'm using a BO of 3, the transaction is open with the datasource of 2.
moreover, if i do a persist i have the message :
AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
BUT if i launch the jar 1 alone (for example), everything is working perfectly.
thanks a lot for your enlightement.
Let me guess:
in your servlet-context.xml, do you import the contexts? e.g.:
<import location="classpath:context1.xml" />
<import location="classpath:context2.xml" />
etc.
If you do, all bean definitions are copied from the imported context into the root context, which means that you have four different <tx:annotation-driven /> declarations, with different transaction managers. Probably the last one wins.
Possible solutions: Either use Qualifiers or use the XML style of transaction declaration.
What I'd do is probably to introduce a custom #Transactional annotation per context:
#Transactional("tx1")
#Inherited
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE,ElementType.METHOD})
public #interface Transactional1 {}
Now annotate all methods in jar 1 with #Transactional1, in jar 2 with #Transactional2 etc. This mechanism is documented in the Section 10.5.6.3 Custom shortcut annotations

Delay task:scheduler first execution in Spring 3

I have a simple application that uses Spring 3 for dependency injection. I have a JFrame for the user to look at and some background tasks for synchronizing with a back-end server and local database maintenance.
This is the relevant part of my application context:
<task:scheduler id="scheduler" pool-size="1"/>
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="synchronizer" method="incrementalSync" fixed-delay="600000"/>
... more tasks ...
</task:scheduled-tasks>
<bean id="mainFrame" class="nl.gdries.myapp.client.ui.MainFrame">
... properties and such ...
</bean>
When I start this applicationContext the scheduler immediately starts executing the background tasks even while my UI is loading. Because the first task is a rather heavy one at the start I want it to wait for the UI to fully load and display before it starts execution.
Does anyone know how to tell Spring to delay executing the scheduled tasks until a moment of my choosing?
This seems to have been left out of the <task:scheduled> bean definition, something I only just noticed last week.
Remember, though, that the <task:...> definitions are just shortcuts, you can always use the explicit approach, by defining a ScheduledExecutorFactoryBean, with nested ScheduledExecutorTask beans. This gives you much finer control, including initialDelay.
I've had the same problem and came back to TimerTask as it is in 25.7.1 point in http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html
<bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<!-- wait 25 seconds before starting repeated execution -->
<property name="delay" value="25000" />
<!-- run every 50 seconds -->
<property name="period" value="50000" />
<property name="timerTask" ref="task" />
</bean>
<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="scheduledTask" />
</list>
</property>
</bean>
I hope in Spring 3.1 will be initialDelay attribute in <task:scheduled>, since in Spring 3.0 TimerFactoryBean is Deprecated.
You can vote for this issue: jira.springframework.org/browse/SPR-7022
This has been introduced by the way in spring 3.2 so if you use the 3.2 schema it's available again -- e.g.:
<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
....
the above allows you to do this:
<task:scheduler id="scheduler" pool-size="1"/>
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="synchronizer" method="incrementalSync" fixed-delay="600000" initial-delay="initial delay needed for the app to start"/>
... more tasks ...
</task:scheduled-tasks>

Categories

Resources