Home > other >  How to change this Spring Batch @Scheduled() annotation in order to specify execution hour and time?
How to change this Spring Batch @Scheduled() annotation in order to specify execution hour and time?

Time:10-21

I am working on a Spring Batch application performing a Job. The Job is scheduled using a Spring CRON expression.

Into my project I have this SpringBatchExampleJobLauncher class:

@Component
public class SpringBatchExampleJobLauncher {

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

    private final Job job;
    private final JobLauncher jobLauncher;
    private ExecutionContext executionContext;

    @Autowired
    public SpringBatchExampleJobLauncher(@Qualifier("updateNotaryDistrictsJob") Job job, 
                                         JobLauncher jobLauncher,
                                         ExecutionContext executionContext) {
        this.job = job;
        this.jobLauncher = jobLauncher;
        this.executionContext = executionContext;
    }

    @Scheduled(cron = "0/10 * * * * *")
    public void runSpringBatchExampleJob() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
        LOGGER.info("Spring Batch example job was started");
        
        List<NotaryDistrict> notaryDistrictsList = new ArrayList<NotaryDistrict>();
        executionContext.put("notaryDistrictsList", notaryDistrictsList);
        
        jobLauncher.run(job, newExecution());

        LOGGER.info("Spring Batch example job was stopped");
    }

    private JobParameters newExecution() {
        Map<String, JobParameter> parameters = new HashMap<>();

        JobParameter parameter = new JobParameter(new Date());
        parameters.put("currentTime", parameter);

        return new JobParameters(parameters);
    }
}

In this specific example the used CRON exception is:

@Scheduled(cron = "0/10 * * * * *")

so the job is performed every 10 seconds. This worsk fine but it is not good for a real case scenario. I have to perform my Job at a specific hour and minute every day

In accordance with what is shown in this post: Spring cron vs normal cron?

and also this documentation: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html

I know that, doing in the following way, I can perform my job at 12:00 PM on the first day of every month.

"0 0 12 1 * *"

and now I have two problem:

  1. For test purposes I must perform my job something like every 18:30 of every day (basically I want do specify not only the hour but also the time of when the job must be executed. Moreover I want perform it every day and not on the first day of the month as specified by the previous expression). How can I modify this CRON expression in order to obtain the desired behavior?

  2. For a next production phase I have to change this behavior in order to perform my job at a specific day (for example Moday) of a specific week (for example every 2 weeks) in a specific hour and time. For example: the job must be performed the first Monday and the third on the month at 02:30 pm. How can I modify this CRON expression in order to obtain the desired behavior?

Thank you

CodePudding user response:

From Spring documentation, the format for Cron expressions is:

 ┌───────────── second (0-59)
 │ ┌───────────── minute (0 - 59)
 │ │ ┌───────────── hour (0 - 23)
 │ │ │ ┌───────────── day of the month (1 - 31)
 │ │ │ │ ┌───────────── month (1 - 12) (or JAN-DEC)
 │ │ │ │ │ ┌───────────── day of the week (0 - 7)
 │ │ │ │ │ │          (or MON-SUN -- 0 or 7 is Sunday)
 │ │ │ │ │ │
 * * * * * *
  1. You can achieve the first case with 0 30 18 * * *. Asterisk * means every in cron expressions.
  2. For this you can use 0 30 14 ? * MON#1,MON#3. MON#X means the Xth Monday of the month. In this case we use ? for day of the month field, because it doesn't matter which day of the month the first/third Monday falls on. ? indicates no specific value.

CodePudding user response:

About the two questions:

First off all, for this case, you have to avoid putting the cron expression directly in the annotation:

@Scheduled(cron = "0/10 * * * * *") // CURRENT

One step to get the solution is defining a property in the application.yml, like:

cron:
    expresion: 0/10 * * * * *

And the code:

@Scheduled(cron = "${cron.expression}")

Doing that, you can have an application.yml by environment, i.e: application-prod.yml with the production cron, and run it with prod profile. Or even override the property at startup by command line:

java -jar your-app.jar --cron.expression=0/15 * * * * *

The same case for testing, you will have your application-test.yml with a tunned property for testing.

  • Related