The exception “java.lang.IllegalStateException: Encountered invalid @Scheduled method ‘task’: Invalid time zone specification” is thrown in the spring boot scheduler on invalid time zone configured.
Schedulers are the tasks that run at a certain interval on a regular basis. Spring boot offers good support for spring boot schedulers. It is possible to configure these schedulers as cron job. By default, cron time takes the time zone of the system. Spring boot allows for different time zone configuration.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerZone' defined in file [D:/workspace/SpringHelloWorld/target/classes/com/yawintutor/Scheduler.class]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: Encountered invalid @Scheduled method 'task': Invalid time zone specification 'AIST' at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE] at com.test.SpringSchedulerApplication.main(SpringSchedulerApplication.java:12) [classes/:na] Caused by: java.lang.IllegalStateException: Encountered invalid @Scheduled method 'task': Invalid time zone specification 'AIST' at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.processScheduled(ScheduledAnnotationBeanPostProcessor.java:499) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$null$1(ScheduledAnnotationBeanPostProcessor.java:362) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE] at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_101] at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$postProcessAfterInitialization$2(ScheduledAnnotationBeanPostProcessor.java:362) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE] at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:1.8.0_101] at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.postProcessAfterInitialization(ScheduledAnnotationBeanPostProcessor.java:361) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:431) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1807) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE] … 14 common frames omitted
Root Cause
In spring boot, cron jobs are used to create schedulers. By default, cron time takes the time zone of the system. Spring boot makes the selection in different time zone. The zone must have the proper time region name. If an invalid name of the time zone is configured, the application will throw this exception.
A time zone is an offset from UTC or GMT to the local time. An offset is simply one characteristic of a time zone. Time zones may have two offsets – one that is followed during “standard time”, and one that is followed during summer time or “daylight time”
How to reproduce this issue
In spring boot application, the @Scheduler annotation contains “zone” parameter. The zone must have the proper time region name. The exception will occur if we configure a invalid time zone in the “zone” parameter. The code below reproduces the exception above.
package com.yawintutor;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class Scheduler {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@Scheduled(cron = "0/5 * * ? * *", zone="AIST")
public void task() {
System.out.println("Scheduler task with duration : " + sdf.format(new Date()));
}
}
Solution 1
Configure the correct time region name of the global time zone in the @Scheduled annotation zone parameter. In the example below, the zone is configured with “IST” Indian standard time zone ( GMT +5.30).
package com.yawintutor;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class Scheduler {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@Scheduled(cron = "0/5 * * ? * *", zone="IST")
public void task() {
System.out.println("Scheduler task with duration : " + sdf.format(new Date()));
}
}
Solution 2
The zone parameter in @Schedule annotation allows the time region to be configured using the GMT time format. Configure with GMT time of the global time zone in the @Scheduled annotation zone parameter. The example below shows how to configure zone using GMT time format. In this example “GMT+5.30” is configured instead of time region name “IST”.
package com.yawintutor;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class Scheduler {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@Scheduled(cron = "0/5 * * ? * *", zone="GMT+5.30")
public void task() {
System.out.println("Scheduler task with duration : " + sdf.format(new Date()));
}
}