How to describe Spring scheduler which is run after application is started and after 00:00 ?
I would do this with two separate constructs.
For after the application starts, use @PostConstuct
, and for every night at midnight use @Scheduled
with the cron
value set. Both are applied to a method.
public class MyClass {
@PostConstruct
public void onStartup() {
doWork();
}
@Scheduled(cron="0 0 0 * * ?")
public void onSchedule() {
doWork();
}
public void doWork() {
// your work required on startup and at midnight
}
}
doWork
method would be invoked multiple times in quick succession. –
Depreciable @EnableScheduling
annotation –
Cousin A little about this subject, you can use @EventListener annotation.
Here is an example :
@Component
public class MyScheduler {
@EventListener(ApplicationReadyEvent.class)
public void onSchedule() {
doWork();
}
public void doWork() {
// your work required on startup
}
}
Combination of solution of nicholas.hauschild and Philippe Gibert. Reason: @PostConstruct is probably not what you want because you may need other services which are still not started.
public class MyClass {
@EventListener(ApplicationReadyEvent.class)
@Scheduled(cron="0 0 0 * * ?")
public void onSchedule() {
doWork();
}
public void doWork() {
// your work required on startup and at midnight
}
}
Consider to catch exceptions inside doWork().
At first you should add @EnableScheduling
annotation for your application config.
The second add @Component
or @Service annotation for your scheduler.
And if you are using Scheduled
annotation it runs automatically after initialization to change it you can use initialDelay
parameter in annotation.
Here is complete example
@Component
public class MyScheduler {
@Scheduled(cron="*/10 * * * * *")
public void onSchedule() {
doWork();
}
public void doWork() {
// your work required on startup and at midnight
}
}
There is a little problrm: when you try to compound two way of start your job, like
@Scheduled(cron = "0/15 * * * * *")
@EventListener(ApplicationReadyEvent.class)
than first time you job starts to work in main thread by listener, and another in scheduling thread by schedulingExcutor. And 2 threads can start to do the same job, even if the first thred hasn't stopped yet! fg:
@Scheduled(cron = "0/15 * * * * *")
@EventListener(ApplicationReadyEvent.class)
public void doWork() {
log.info("I'm working!!!!!");
try {
TimeUnit.SECONDS.sleep(60);
} catch (InterruptedException e) {
log.info("I was interrupted!");
}
log.info("I finished work");
}
log:
16:32:36.086 INFO 34472 --- [ main] hello.jobs.CronJob: I'm working!!!!!
16:32:45.005 INFO 34472 --- [ scheduling-1] hello.jobs.CronJob: I'm working!!!!!
16:33:36.090 INFO 34472 --- [ main] hello.jobs.CronJob: I finished work
16:33:45.011 INFO 34472 --- [ scheduling-1] hello.jobs.CronJob: I finished work
We have multiple approaches to execute it, The suggested approach by the @nicholas.hauschild is correct and easier than any other approach, but with the @PostConstruct
we must be careful not to use the method of the dependent bean. That bean may not have been initialized yet and cause a NullPointerException
.
So we can implement CommandLineRunner
or ApplicationRunner
and implement the run method, So by that run method will be automatically invoked after all beans are initialized and the app has been started.
@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
@Autowired
private MyClass MyClass;
@Override
public void run(String...args) throws Exception {
myService.doWork();
}
}
okay, as I understand you want to run your schedule job once the app is started and at every midnight.
Spring Scheduler offers initialDelay
but you have to use it with fixedDelay
.
here is my answer:
// it runs after 30 seconds of startup, you will be dead before it runs again.
@Scheduled(initialDelay = 1000 * 30, fixedDelay=Long.MAX_VALUE)
public void runAtStartup(){
doWork();
}
// runs every midgnight (12.00 AM)
@Scheduled(cron="0 0 0 * * ?")
public void onSchedule() {
doWork();
}
public class MyClass {
@PostConstruct
@Scheduled(cron="0 0 0 * * ?")
public void doWork() {
// your work
}
}
@EnableScheduling
annotation is required, this code as such didn't worked. –
Cousin Understanding more about it follow this link https://www.baeldung.com/cron-expressions
For the specific task to be done at midnight there is a predefined annotation that can help , try @midnight
. It should work:
@midnight
public void midnightRun(){
doTheWork();
}
@midnight
annotation that I can find. Add to that, cron expressions should accept the phrase @midnight
instead of the stars-and-numbers. Either way, this doesn't work with my Spring Scheduler at all. Midnight or Daily is 0 0 0 * * *
using the Spring Scheduler. –
Billet © 2022 - 2024 — McMap. All rights reserved.
doWork
be executed twice? – Bewray