Can we create a pool of Spring ScheduledExecutorTask? - java

I'm trying to see if there's a possibility to create a pool of spring ScheduledExecutor. What I need is a set a ScheduledExecutor tasks which will perform certain task in a regular interval. I was trying to use the following way :
<bean id="contentProcessorPool"
class="org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean">
<property name="poolSize" value="${processor.corepoolsize}"/>
<property name="continueScheduledExecutionAfterException" value="true"/>
<property name="scheduledExecutorTasks">
<list>
<ref local="processor"/>
</list>
</property>
<bean id="processor"
class="org.springframework.scheduling.concurrent.ScheduledExecutorTask">
<property name="delay" value="${processor.polling.delay}"/>
<property name="period" value="${processor.polling.period}"/>
<property name="runnable">
<ref local="contentWorker" />
</property>
<bean id="contentWorker" class="com.autodesk.contentextraction.processor.ContentWorker">
</bean>
But this creates one a single ContentWorker instance which keeps running at the specified interval. What I want is a set of ContentWorker to run after a given interval.
Any pointers will be highly appreciated.
Thanks

How about this?
<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="someObject" method="someMethod" fixed-delay="5000"/>
</task:scheduled-tasks>
<task:scheduler id="myScheduler" pool-size="10"/>
Source: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html#scheduling-task-namespace-scheduled-tasks

If you used fixed rate instead of fixed delay the operation will occur exactly at that interval, and not after the following one has complete. I wouldn't have thought you'd need to pool it (manually) after that?
If you don't need explicit control in your context file, you can annotate the class:
import org.springframework.stereotype.Service
org.springframework.scheduling.annotation.Scheduled
Class annotation: #Service
Method annotation: #Scheduled(fixedRate=30000)
Context:
xmlns:task="http://www.springframework.org/schema/task"
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
<task:annotation-driven />

Related

CompositeItemReader in Spring

In Spring Batch, in the job-request.xml file you can have the chunk's writer run a "compositeItemWriter" which looks something like this:
<bean id="compositeItemWriter"
class="org.springframework.batch.item.support.CompositeItemWriter">
<property name="delegates">
<list>
<ref bean="writer1" />
<ref bean="writer2" />
</list>
</property>
</bean>
I was wondering if there's anything similar for readers? I tried using org.springframework.batch.item.support.CompositeItemStream but apparently delegates does not exist as a property. Putting "reader1" or "reader2" in the delegates property list in compositeItemWriter similarly does not work (cannot convert readers to writers)
Any advice would be greatly appreciated
Thanks!
MultiResourceItemReader reads items from multiple resources sequentially:
http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/item/file/MultiResourceItemReader.html
It will look like:
<bean id="itemReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
<property name="resources" value="LIST_OF_FILES" />
<property name="delegate" ref="itemReaderDelegate" />
</bean>

spring batch sleep between steps

How can I make a spring batch job sleep between executions if the next step is itself?
For example
<batch:step id="messages" next="messages">
.....
</batch:step>
I have tried using the parent="simpleJob" with the following configuration only to get unique key constraints. Not sure what I am missing.
<bean id="simpleJob" class="org.springframework.batch.core.job.SimpleJob" abstract="true">
<property name="jobRepository" ref="jobRepository"/>
</bean>
<bean id="runScheduler" class="com.test.boa.scheduler.RunScheduler">
<property name="dataSource" ref="dataSource"/>
</bean>
<task:scheduled-tasks>
<task:scheduled ref="runScheduler" method="run" fixed-delay="500000"/>
</task:scheduled-tasks>
The runScheduler is getting the next key but it seems like that doesn't get incremented upon step completion.
Any help would be appreciated.
You will need to set up listeners to intercept the before and after methods for your steps.
http://docs.spring.io/spring-batch/trunk/reference/html/configureStep.html#interceptingStepExecution

Upgrading to springframework.scheduling.concurrent?

As of Spring 3.0 the ScheduledTimerTask is deprecated and I can't understand how to upgrade to org.springframework.scheduling.concurrent.
<bean id="timerFactoryBean" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="onlineTimeSchedule" />
</list>
</property>
</bean>
<bean id="onlineTimeSchedule" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" class="com.example.OnlineTimerTask" />
</property>
<property name="period" value="60000" />
<property name="delay" value="1000" />
</bean>
Where the OnlineTimerTask extends java.util.TimerTask. It's simple task which publishes a message to publisher every minute. I checked the documentation, but nothing.. I can't understand which way to use from the concurrent package and which suits the best.
Also I want to turn this xml into #Bean in Java.
EDIT: So I tried to implement the xml with #Bean and #Configuration instead and here is what I got.
#Configuration
public class ContextConfiguration {
#Bean
public ScheduledExecutorFactoryBean scheduledExecutorFactoryBean() {
ScheduledExecutorFactoryBean scheduledFactoryBean = new ScheduledExecutorFactoryBean();
scheduledFactoryBean.setScheduledExecutorTasks(new ScheduledExecutorTask[] {onlineTimeSchedule()});
return scheduledFactoryBean;
}
#Bean
public ScheduledExecutorTask onlineTimeSchedule() {
ScheduledExecutorTask scheduledTask = new ScheduledExecutorTask();
scheduledTask.setDelay(1000);
scheduledTask.setPeriod(60000);
scheduledTask.setRunnable(new OnlineTimerTask());
return scheduledTask;
}
}
Will the code above be correct replacement for xml? Will in my case the setScheduledExecutorTasks work properly? I mean will the referencing to the same bean instance, if onlineTimeSchedule() is called more than once, will work here?
scheduledFactoryBean.setScheduledExecutorTasks(new ScheduledExecutorTask[] {onlineTimeSchedule()});
Use org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean in place of org.springframework.scheduling.timer.TimerFactoryBean and use org.springframework.scheduling.concurrent.ScheduledExecutorTask in place of org.springframework.scheduling.timer.ScheduledTimerTask. You will need to adjust the property names and values as needed but, that should be pretty self evident.
Optionally, you could refactor your com.example.OnlineTimerTask to not extend java.util.TimeTask as the ScheduledTimerTask only requires a runnable.
Spring 4 configuration - Below configuration working after spring migration from 3.2.x to 4.6.x
<bean id="schedulerTask"
class="org.springframework.scheduling.support.MethodInvokingRunnable">
<property name="targetObject" ref="springJmsListnerContainer" />
<property name="targetMethod" value="execute" />
</bean>
<bean id="timerTask" class="org.springframework.scheduling.concurrent.ScheduledExecutorTask">
<property name="runnable" ref="schedulerTask" />
<property name="delay" value="100" />
<property name="period" value="60000" />
</bean>
<bean class="org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean">
<property name="scheduledExecutorTasks">
<list>
<ref bean="timerTask" />
</list>
</property>
</bean>
The answer is - add one "runnable" field
<bean id="scheduledExecutorTask"
class="org.springframework.scheduling.concurrent.ScheduledExecutorTask">
<!-- wait 10 milli seconds before starting repeated execution -->
<property name="delay">
<value>10</value>
</property>
<!-- run every 1 second -->
<property name="period">
<value>1000</value>
</property>
<property name="runnable">
<ref bean="checkInvokingTask"/>
</property>
</bean>

How to execute method using spring beans

I need findItemByPIdEndDate() method of the MngtImpl class to be invoked every 5000ms, but nothing appears to be happening. Am I missing something?
<bean id="findItemByPIdEndDate" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="MngtImpl"/>
<property name="targetMethod" value="findItemByPIdEndDate"/>
<property name="repeatInterval" value="50000"/>
</bean>
#matt b I've read some of this, everything is new to me here ..so I came with this .. and again its not working, what am I missing this time ?
<bean id="findItemByPIdEndDate" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="MngtImpl" />
<property name="targetMethod" value="findItemByPIdEndDate" />
</bean>
<bean id="compareDateTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="findItemByPIdEndDate" />
<property name="startDelay" value="0" />
<property name="repeatInterval" value="50000" />
</bean>
For this task, the Chapter 23. Scheduling and Thread Pooling is your friend. That said, here is a short summary.
First, define your Job:
<bean id="findItemByPIdEndDate" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="MngtImpl"/>
<property name="targetMethod" value="findItemByPIdEndDate"/>
</bean>
Now, you need to schedule the job using a trigger and a SchedulerFactoryBean. For the trigger, I suggest to use a SimpleTriggerBean in your case:
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<!-- see the example of method invoking job above -->
<property name="jobDetail" ref="findItemByPIdEndDate" />
<!-- 10 seconds -->
<property name="startDelay" value="10000" />
<!-- repeat every 50 seconds -->
<property name="repeatInterval" value="50000" />
</bean>
To finalize everything, set up the SchedulerFactoryBean:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
</bean>
You need a lot more plumbing than that to make Quartz work. Just declaring the MethodInvokingJobDetailFactoryBean on its own will do nothing.
However, Quartz is overkill for this, Java5+ can do this on its own. I suggest reading up on Spring's ScheduledExecutorFactoryBean, which in combination with MethodInvokingRunnable, allows you to invoke your method periodically.
What you've done so far is the equivalent of only instantiating a MethodInvokingJobDetailFactoryBean() - essentially all you've done is created the Job. Now you need to have some configuration for how it's scheduled, and what triggers it.
Take a look at the section in the Spring manual on Quartz.

Using Quartz with Spring

In my application there is a requirement to be able to create Scheduled Job(s) depending on the type of Request that comes in (Dynamically).
Can I still use Spring to create and trigger Jobs? If Yes, how?
Any help would be useful.
Given that the SchedulerFactoryBean exposes a native Quartz Scheduler object, you can wire that directly into your controller class, and then dynamically create and register triggers and jobs with the Scheduler object.
Spring itself can't be used for the scheduling of the dynamically created jobs, since Spring's bean support will be used for statically configured jobs, but the native Quartz Scheduler API is reasonable enough to use on its own (barely). As fr triggering of the jobs, that Quartz's job, not Spring's.
edit: either I'm mis-understanding the original question, or everyone else is. The other answers all detail how to statically wire up a series of quartz jobs using Spring, but the question was how to dynamically schedule jobs as requests come in.
Look at CronTriggerBean and JobDetailBean. The 'MyJob' class mocked up below is an instance of QuartzJobBean. The cron expression is what you'd expect, but with seconds as its first value.
<beans>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="startupDelay" value="5"/>
<property name="waitForJobsToCompleteOnShutdown" value="false"/>
<property name="triggers">
<list>
<bean class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="edu.vt.MyJob"/>
<property name="jobDataAsMap">
<map>
<entry key="messageSource" value-ref="messageSource"/>
<entry>
<key><value>anotherProperty</value></key>
<bean class="edu.vt.MyUsefulBean">
<constructor-arg index="0" value="..."/>
</bean>
</entry>
</map>
</property>
</bean>
</property>
<property name="cronExpression" value="0 * * * * ?"/>
</bean>
</list>
</property>
</bean>
</beans>
There does not seem to be much complete information on this. This is how I schedule jobs dynamically. Of course you could replace the simple trigger with some other trigger.
Spring beans:
<bean name="dailyUpdateJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.somecompany.scheduler.DailyUpdates" />
</bean>
<bean id="dailyCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="dailyUpdateJob" />
<!-- run every morning at 4:15 AM -->
<property name="cronExpression" value="00 15 04 * * ?" />
</bean>
<bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="dailyCronTrigger" />
<ref bean="weeklyReportsCronTrigger" />
</list>
</property>
<property name="applicationContextSchedulerContextKey">
<value>applicationContext</value>
</property>
</bean>
To run the job immediately get a reference to the scheduler and the job, attach a simple trigger and put it into the scheduler, like this:
#Autowired
SchedulerFactoryBean scheduler;
#Autowired
#Qualifier("dailyUpdateJob")
JobDetailFactoryBean dailyJob;
public void dynamicJobTrigger() throws Exception {
// Create a trigger for "now"
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.startAt(new Date())
.forJob(dailyJob.getObject())
.build();
// And drop it into the scheduler for immediate execution
scheduler.getScheduler().scheduleJob(trigger);
}
You can download sample source code from this link
<?xml version="1.0" encoding="UTF-8"?>
<!-- scheduler factory -->
<bean id="com.notary.app.invoicing.scheduler.SchedulerFactory"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="ASFImportTrigger"/>
</list>
</property>
<property name="dataSource">
<ref bean="datasource"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="quartzProperties">
<props>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.MSSQLDelegate</prop>
<prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
<prop key="org.quartz.jobStore.selectWithLockSQL">SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?</prop>
<prop key="org.quartz.plugin.triggHistory.class">org.quartz.plugins.history.LoggingTriggerHistoryPlugin</prop>
<prop key="org.quartz.plugin.triggHistory.triggerFiredMessage">Trigger {1}.{0} fired job {6}.{5} at: {4, date, HH:mm:ss dd/MM/yyyy}</prop>
<prop key="org.quartz.plugin.triggHistory.triggerCompleteMessage">Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH:mm:ss dd/MM/yyyy} with resulting trigger instruction code: {9}</prop>
<prop key="org.quartz.plugin.jobHistory.class">org.quartz.plugins.history.LoggingJobHistoryPlugin</prop>
<prop key="org.quartz.plugin.jobHistory.jobSuccessMessage">Job {1}.{0} fired at: {2, date, dd/MM/yyyy HH:mm:ss} result=OK</prop>
<prop key="org.quartz.plugin.jobHistory.jobFailedMessage">Job {1}.{0} fired at: {2, date, dd/MM/yyyy HH:mm:ss} result=ERROR</prop>
</props>
</property>
<property name="overwriteExistingJobs" value="true"/>
<property name="startupDelay" value="50"/>
<property name="applicationContextSchedulerContextKey">
<value>applicationContext</value>
</property>
</bean>
You can also get Spring to trigger methods on your beans using Quartz (i.e. youdon't need to create any Quartz-specific classes at all) using the MethodInvokingJobDetailFactoryBean in the package org.springframework.scheduling.quartz
A year later and I find myself having to something very similar. Googling around, I found this link which describes getting access to the application context from within a scheduled job through the JobExecutionContext. I think I will be creating an abstract type job that can do some of the actual job creation and use a prototype to actual inject required services when the job needs to run.
Spring 3 (latest version at time of writing) supports setting up jobs almost completely with annotations.
See: Spring reference on scheduling

Categories

Resources