AFAIK there is no standard way in Java to detect if the system went in standby/hibernate. Scheduling in Spring is based on the timing facilites in Java, facilites which are not intended to work across OS sleep or hibernate conditions. In short, if the JVM cannot detect when system goes in standby neither can Spring.
As I see it you have the following options:
- notify the application when the system is resumed then re-schedule the tasks. This is a possible solution built around pm utils on Ubuntu. This one is for Windows.
- add an additional task that runs, say every 10 seconds and reads the system time. If there is an appreciable difference between two time readings it means your system went to sleep and then resumed.
The following for example restarts the context if a time gap (delta
) greater than 1s is detected:
@SpringBootApplication
@EnableScheduling
public class Application {
private static ConfigurableApplicationContext context;
public static void main(String[] args) {
context = SpringApplication.run(Application.class, args);
}
static LocalTime lastDetectedTime;
static long delta = 1000;
static final long CHECK_INTERVAL = 5000;
@Scheduled(fixedDelay = CHECK_INTERVAL, initialDelay = CHECK_INTERVAL)
public static void restartIfTimeMismatch() {
if(lastDetectedTime == null) {
lastDetectedTime = LocalTime.now();
}
LocalTime currentTime = LocalTime.now();
long diff = Duration.between(lastDetectedTime, currentTime).toMillis();
lastDetectedTime = currentTime;
if(diff > CHECK_INTERVAL + delta) {
Thread thread = new Thread(() -> {
context.close();
context = SpringApplication.run(Application.class);
});
lastDetectedTime = null;
thread.setDaemon(false);
thread.start();
}
}
}
Hope it helps.