Search code examples
spring-batchquartz-scheduler

How can I add multiple spring batch jobs inside the scheduling configurer?


So below sample java class configuration will get the CRON job expression from the database dynamically. So far it works only in 1 job. However, I have another job and tried adding it by invoking addTriggerTask method but job failed due to this error. Any recommendation how we can trigger multiple jobs?

   ERROR: required a single bean, but 2 were found
    
   Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
@Configuration
@EnableScheduling
public class DynamicScheduler implements SchedulingConfigurer {

    private static Logger LOGGER = LoggerFactory.getLogger(DynamicScheduler.class);

    @Autowired
    ConfigRepo repo;

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    private Job job;


    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {

        taskRegistrar.addTriggerTask(() -> executeJob("job1"), t -> {
            CronTrigger crontrigger = new CronTrigger(repo.findById("cronExpressionJob1").get().getConfigValue());

            return crontrigger.nextExecutionTime(t);
        });

    }

    public void executeJob(String jobName) {        

        try {

            JobParameters jobParameters = new JobParametersBuilder()
                    .addString(jobName, String.valueOf(System.currentTimeMillis())).toJobParameters();

            jobLauncher.run(job, jobParameters);
        } catch (Exception e) {
            LOGGER.error("Failed due to exception thrown.", e);
        }

    }

}


Solution

  • In your current code, you are using @Autowired to inject a Job into DynamicScheduler. This is unambiguous when you only have a single job, but as soon as you add another job Spring cannot disambiguate which job you want injected.

    That's why you are seeing the error:

    ERROR: required a single bean, but 2 were found

    Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

    If you want to handle multiple jobs, then I suggest removing @Autowired private Job job; from your class and use a JobRegistry to look up your Job by name as a local variable. Then pass that Job along with its JobParameters to jobLauncher.run().

    // get JobParameters for jobName
    Job job = jobRegistry.getJob( jobName );
    jobLauncher.run( job, jobParameters );