Search code examples
javaspringspring-batchspring-xd

Spring Step Scheduling


I'm trying to schedule steps in a Spring Batch job. I tried using . But When I'm trying to deploy the job on SpringXd its failing. Below is my code and error I'm facing

<batch:job id="addB" restartable="false">
<batch:step id="AddB" >
        <tasklet ref="addBTasklet" />
</batch:step>
</batch:job>

<task:scheduler id="taskScheduler" pool-size="1"/>
        <task:scheduled-tasks scheduler="taskScheduler">        
        <task:scheduled ref="AddB" method="execute" cron="*/5 * * * * ?"/>
 </task:scheduled-tasks>

I am getting this error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'org.springframework.scheduling.support.ScheduledMethodRunnable#0': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: 
Failed to instantiate [org.springframework.scheduling.support.ScheduledMethodRunnable]:` Constructor threw exception; nested exception is java.lang.NoSuchMethodException: 
org.springframework.batch.core.step.tasklet.TaskletStep.execute()

Solution

  • You would need to add a class that implements the required logic to start a job and then let the scheduler call a method in that class. Contents of this new class:

    package mypackage;
    
    import org.springframework.batch.core.Job;
    import org.springframework.batch.core.JobExecution;
    import org.springframework.batch.core.JobParameters;
    import org.springframework.batch.core.JobParametersBuilder;
    import org.springframework.batch.core.launch.JobLauncher;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Service;
    
    import java.util.UUID;
    
    @Service
    public class TriggerScheduledJob {
    
        @Autowired
        private JobLauncher jobLauncher;
    
        @Autowired
        @Qualifier("addB")
        private Job addBJob;
    
        @Autowired
        @Qualifier("addC")
        private Job addCJob;
    
        public void triggerAddB() {
            JobParameters param = new JobParametersBuilder().addString("id", UUID.randomUUID().toString()).toJobParameters();
            try {
                JobExecution execution = jobLauncher.run(addBJob, param);
                System.out.println("Job executed with exit status = " + execution.getStatus());
            } catch (Exception e) {
                System.out.println("Failed to execute job. " + e.getMessage());
            }
        }
    
        public void triggerAddC() {
            JobParameters param = new JobParametersBuilder().addString("id", UUID.randomUUID().toString()).toJobParameters();
            try {
                JobExecution execution = jobLauncher.run(addCJob, param);
                System.out.println("Job addC executed with exit status = " + execution.getStatus());
            } catch (Exception e) {
                System.out.println("Failed to execute job. " + e.getMessage());
            }
        }
    }
    

    Then adjust your Spring application context so that it creates this new bean, and modify the scheduler to call the relevant method of that bean to trigger the actual job you want to start:

    <batch:job id="addB" restartable="false">
        <batch:step id="AddB" >
            <tasklet ref="addBTasklet" />
        </batch:step>
    </batch:job>
    
    <batch:job id="addC" restartable="false">
        <batch:step id="AddC" >
            <tasklet ref="addCTasklet" />
        </batch:step>
    </batch:job>
    
    <bean id="triggerScheduledJob" class="mypackage.TriggerScheduledJob" />
    
    <task:scheduler id="taskScheduler" pool-size="1"/>
    <task:scheduled-tasks scheduler="taskScheduler">        
        <task:scheduled ref="triggerScheduledJob" method="triggerAddB" cron="*/5 * * * * ?"/>
    </task:scheduled-tasks>
    <task:scheduled-tasks scheduler="taskScheduler">        
        <task:scheduled ref="triggerScheduledJob" method="triggerAddC" cron="*/5 * * * * ?"/>
    </task:scheduled-tasks>
    

    Hope it brings you forward.