spring batch sleep between steps - java

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

Related

Spring Batch - Is there a way create a Stored Procedure step which neither reads nor writes?

I have a stored procedure that runs at the end of a chain of steps that merely merges the resulting data on the database itself. I have no need to read nor write any data as a result. Just a successful execution is enough.
Is there a simple way to do this?
My step looks something like this so far...
<batch:step id="CleanupStep">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="MergeCleanup"
writer="NoOpWriter"/>
<batch:transaction-attributes propagation="NEVER"/>
</batch:tasklet>
</batch:step>
<bean id="MergeCleanup"
class="org.springframework.batch.item.database.StoredProcedureItemReader" scope="step">
<property name="dataSource" ref="DataSource"/>
<property name="procedureName" value="MERGE_CLEANUP"/>
</bean>
<bean id="NoOpWriter"
class="my.package.NoOpWriter">
</bean>
Using a TaskletStep is the right solution.
You can found many examples around the net.

executing multiple processing class with Spring batch processing

I am new to spring batch processing . Just wanted few suggestion so that i could connect while reading about spring batch.
My scenario is as follows:
I wrote 4 java classes which would read and modify data in oracle.
For example : Class1 and Class2 will modify table 1, Class3 and Class4 will modify table2
How can we parallelize execution of there classes with spring batch processiing?
Without knowing what each class does, there's a limit on how good of advice I can provide. That being said, if all you want to do is to execute each class in parallel using Spring Batch, Spring Batch provides a couple of tools to help with this:
Split - A split in Spring Batch is the division of the flow so that steps can be executed in parallel. In your case, I'd expect either two or four flows to be executed in parallel (depending on if you need to execute Class1 -> Class 2 in sequence but that sequence in parallel with Class3 -> Class4, or if you can just run all four classes in parallel).
MethodInvokingTaskletAdapter - This Tasklet implementation provided by Spring Batch allows you to execute a method on a specified bean in the scope of a transaction. This allows you to wrap existing classes with a Tasklet so they can be easily consumed by Spring Batch.
With the above concepts in place, you could configure your batch job to look something like the following:
<job id="job1">
<split id="split1">
<flow>
<step id="split1Step1" next="split1Step2">
<tasklet ref="class1Tasklet"/>
</step>
<step id="split1Step2">
<tasklet ref="class2Tasklet"/>
</step>
</flow>
<flow>
<step id="split2Step1" next="split2Step2">
<tasklet ref="class3Tasklet"/>
</step>
<step id="split2Step2">
<tasklet ref="class4Tasklet"/>
</step>
</flow>
</split>
</job>
<bean id="class1Tasklet" class="org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter">
<property name="targetObject">
<bean class="Class1"/>
</property>
<property name="targetMethod" value="someMethod"/>
</bean>
<bean id="class2Tasklet" class="org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter">
<property name="targetObject">
<bean class="Class2"/>
</property>
<property name="targetMethod" value="someMethod"/>
</bean>
<bean id="class3Tasklet" class="org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter">
<property name="targetObject">
<bean class="Class3"/>
</property>
<property name="targetMethod" value="someMethod"/>
</bean>
<bean id="class4Tasklet" class="org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter">
<property name="targetObject">
<bean class="Class4"/>
</property>
<property name="targetMethod" value="someMethod"/>
</bean>
You can read more about the MethodInvokingTaskletAdapter in the documentation here: http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapter.html

CronTrigger misfire instruction is not set with CronTriggerFactoryBean

I'm creating a Quartz job with the following Spring XML configuration:
<bean class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="name" value="The job"/>
<property name="group" value="The group"/>
<property name="jobClass" value="com.example.myapp.MorningJob"/>
<property name="jobDataMap">
<util:map>
<entry key="key1"
value="val1"/>
<entry key="key2"
value="val2"/>
</util:map>
</property>
</bean>
</property>
<property name="cronExpression" value="0 0 6 * * ? *"/>
<property name="misfireInstruction"
value="#{T(org.quartz.CronTrigger).MISFIRE_INSTRUCTION_FIRE_ONCE_NOW}"/>
<property name="timeZone" ref="timezone"/>
</bean>
My job looks like this
#Configurable
#DisallowConcurrentExecution
#PersistJobDataAfterExecution
public class MorningJob implements Job { ... }
However, misfire instruction set has no effect at all. After long app downtime, when the trigger missed multiple times, Quartz tries to start the job many times.
When I'd tried to check context.getTrigger().getMisfireInstruction() from MorningJob.execute() it gives 0, while CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW is 1.
Any ideas why misfire instruction is not set?
The problem was actually in my scheduler configuration. In the declaration of org.springframework.scheduling.quartz.SchedulerFactoryBean I had a property
<property name="overwriteExistingJobs" value="false"/>
Initially, for testing purposes I've configured my trigger to run each few seconds just to see it fires properly. overwriteExistingJobs meant the trigger saved in database wasn't actually updated after change of cron expression and misfireInstruction wasn't actually applied as well. To update the trigger I need either to run scheduler.clear() once or set the mentioned property to true for a while.
I'm sure this should be mentioned more clearly in the documentation as it could be really frustrating to not have a trigger configuration updated after each change. false is the default value of overwriteExistingJobs.

Is there something that starts a cron in java?

I have some java written to do a very very simple operation. It needs to happen once every three hours and is not connected to any user action, it's just something that revolves every three hours.
For this reason, I'm having trouble troubleshooting. The operation isn't happening. Assuming the java is intact, is there something that is supposed to "start" the cron? Or should I expect it to just be going once the server is restarted?
<bean id="queueJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.campbiche.pb.service.scheduler.BaseQuartzScheduler" />
<property name="jobDataAsMap">
<map>
<entry key="processorName" value="scheduleListingActions" />
<entry key="methodName" value="revolveQueue" />
</map>
</property>
</bean>
<bean id="queueCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="queueJob" />
<!-- run every 1 miunute -->
<property name="cronExpression" value="*/1 * * * * ?" />
</bean>
Working in SpringSource. The Cron is set to one minute for testing. "" has already been added to a schedulerfactorybean bean as well but I did not include the code here for brevity.
It will be triggered when CronTriggerBean is instantiated.
One more thing I recall, and confirmed after looking in the docs(3.x), that you need to add your queueCronTrigger to SchedulerFactoryBean.

Can we create a pool of Spring ScheduledExecutorTask?

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 />

Categories

Resources