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:
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?
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)
│ │ │ │ │ │
* * * * * *
- You can achieve the first case with
0 30 18 * * *
. Asterisk*
meansevery
in cron expressions. - For this you can use
0 30 14 ? * MON#1,MON#3
.MON#X
means theX
th 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.