Comment configurer le fuseau horaire d'un travail cron @Scheduled basé sur Spring?
Contexte:
J'ai un travail qui s'exécute une fois par jour, disons 14 heures, en utilisant l'annotation @Scheduled
de Spring:
@Scheduled(cron = "0 0 14 * * *")
public void execute() {
// do scheduled job
}
Le problème est que 2 PM diffère d'un serveur à l'autre, car Spring utilise on TimeZone.getDefault()
en interne . De plus, le JavaDoc de TimeZone.getDefault()
indique que:
Obtient le fuseau horaire par défaut pour cet hôte. La source du fuseau horaire par défaut peut varier en fonction de la mise en œuvre.
En d'autres termes, le fuseau horaire n'est pas déterminé. Cela peut dépendre de la mise en œuvre JVM, de la configuration du fuseau horaire du serveur, de l'emplacement du serveur et/ou d'autres facteurs inconnus. Par conséquent, le travail cron se déclenche à des heures différentes sur des serveurs différents, sauf s’il est possible de définir explicitement le fuseau horaire à utiliser?
J'utilise Spring 3.2.2.
Mettre à jour
À partir du printemps 4, le problème du printemps Jira SPR-10456 était résolu. Par conséquent, l'annotation @Scheduled
a un nouvel attribut zone à cet effet.
Il s'est avéré que je ne pouvais pas utiliser l'annotation @Scheduled
, mais j'ai mis en place une solution de contournement. Dans le JavaDoc du SchedulingConfigurer , il est indiqué que:
[SchedulingConfigurer est] Généralement utilisé pour définir un bean TaskScheduler spécifique lors de l'exécution de tâches planifiées ou pour enregistrer des tâches planifiées de manière programmatique, par opposition à l'approche déclarative consistant à utiliser l'annotation @Scheduled.
Ensuite, j'ai modifié le travail cron pour implémenter l'interface Runnable
, puis mis à jour mon fichier de configuration pour implémenter la SchedulingConfigurer
, voir ci-dessous:
@Configuration
@EnableScheduling
@ComponentScan("package.that.contains.the.runnable.job.bean")
public class JobConfiguration implements SchedulingConfigurer {
private static final String cronExpression = "0 0 14 * * *";
private static final String timeZone = "CET";
@Autowired
private Runnable cronJob;
@Bean
CronTrigger cronTrigger() {
return new CronTrigger(cronExpression, TimeZone.getTimeZone(timeZone));
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addCronTask(new CronTask(job, cronTrigger()));
}
}
Veuillez lire le JavaDoc du @EnableScheduling pour plus d’informations.
Mettre à jour
Au printemps 4, le problème Spring Jira SPR-10456 était résolu. Par conséquent, l'annotation @Scheduled
a un nouvel attribut zone exactement à cette fin.
Il y a un élément zone
dans l'annotation @Scheduled
à partir de la version 4.0.
Vous pouvez insérer un fuseau horaire en tant que chaîne pouvant être acceptée par Java.util.TimeZone
.
Je doute que vous souhaitiez que différents emplois ou parties d'applications utilisent des fuseaux horaires différents. En supposant que tout soit cohérent et à sec, configurez le système d'exploitation sur tous les serveurs pour que le fuseau horaire soit cohérent ou définissez la propriété système Java user.timezone pour tous les serveurs d'applications. Gérez la configuration de manière centralisée (système d’exploitation, serveur d’application), et pour cette marionnette et ce chef peuvent être très utiles.