diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java index 3e9d06f180..1bd28a47ae 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java @@ -103,6 +103,8 @@ public class QuartzAutoConfiguration { if (this.triggers != null && this.triggers.length > 0) { schedulerFactoryBean.setTriggers(this.triggers); } + schedulerFactoryBean + .setOverwriteExistingJobs(this.properties.isOverwriteExistingJobs()); customize(schedulerFactoryBean); return schedulerFactoryBean; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzProperties.java index de33c0e8e5..9b7c6d19f0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzProperties.java @@ -42,6 +42,11 @@ public class QuartzProperties { */ private final Map properties = new HashMap<>(); + /** + * Allows to reschedule existing jobs. + */ + private boolean overwriteExistingJobs = false; + private final Jdbc jdbc = new Jdbc(); public JobStoreType getJobStoreType() { @@ -60,6 +65,14 @@ public class QuartzProperties { return this.jdbc; } + public boolean isOverwriteExistingJobs() { + return this.overwriteExistingJobs; + } + + public void setOverwriteExistingJobs(boolean overwriteExistingJobs) { + this.overwriteExistingJobs = overwriteExistingJobs; + } + public static class Jdbc { private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/quartz/impl/" diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java index 1d65a888de..43e972ff6e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfigurationTests.java @@ -29,6 +29,7 @@ import org.quartz.JobExecutionContext; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SimpleScheduleBuilder; +import org.quartz.SimpleTrigger; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; @@ -158,6 +159,28 @@ public class QuartzAutoConfigurationTests { }); } + @Test + public void withOverwriteExistingJobsParameter() { + this.contextRunner.withUserConfiguration(OverwriteTriggerConfiguration.class) + .withPropertyValues("spring.quartz.overwriteExistingJobs=true", + "test-name=withConfiguredJobAndOverwrittenTrigger") + .run((context) -> { + assertThat(context).hasSingleBean(Scheduler.class); + Scheduler scheduler = context.getBean(Scheduler.class); + assertThat(scheduler.getJobDetail(JobKey.jobKey("fooJob"))) + .isNotNull(); + Trigger fooTrigger = scheduler + .getTrigger(TriggerKey.triggerKey("fooTrigger")); + assertThat(fooTrigger).isNotNull(); + assertThat(((SimpleTrigger) fooTrigger).getRepeatInterval()) + .isEqualTo(30000); + Thread.sleep(1000L); + this.output.expect( + containsString("withConfiguredJobAndOverwrittenTrigger")); + this.output.expect(containsString("jobDataValue")); + }); + } + @Test public void withConfiguredJobAndTrigger() { this.contextRunner.withUserConfiguration(QuartzFullConfiguration.class) @@ -251,6 +274,21 @@ public class QuartzAutoConfigurationTests { } + @Configuration + @Import(QuartzFullConfiguration.class) + protected static class OverwriteTriggerConfiguration extends BaseQuartzConfiguration { + + @Bean + public Trigger anotherFooTrigger(JobDetail fooJob) { + SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule() + .withIntervalInSeconds(30).repeatForever(); + + return TriggerBuilder.newTrigger().forJob(fooJob).withIdentity("fooTrigger") + .withSchedule(scheduleBuilder).build(); + } + + } + @Configuration protected static class QuartzCalendarsConfiguration extends BaseQuartzConfiguration { diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index be06a22a28..a47237dd60 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -146,6 +146,7 @@ content into your application. Rather, pick only the properties that you need. spring.quartz.jdbc.schema=classpath:org/quartz/impl/jdbcjobstore/tables_@@platform@@.sql # Path to the SQL file to use to initialize the database schema. spring.quartz.job-store-type=memory # Quartz job store type. spring.quartz.properties.*= # Additional Quartz Scheduler properties. + spring.quartz.overwriteExistingJobs=false # Whether overwriting existing job definitions is enabled. # REACTOR ({sc-spring-boot-autoconfigure}/reactor/core/ReactorCoreProperties.{sc-ext}[ReactorCoreProperties]) spring.reactor.stacktrace-mode.enabled=false # Whether Reactor should collect stacktrace information at runtime. diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 82411c5f2f..86831c2375 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -5997,7 +5997,7 @@ provided with the Quartz library. It is also possible to provide a custom script setting the `spring.quartz.jdbc.schema` property. Quartz Scheduler configuration can be customized by using Quartz configuration properties -()`spring.quartz.properties.*`) and `SchedulerFactoryBeanCustomizer` beans, which allow +(`spring.quartz.properties.*`) and `SchedulerFactoryBeanCustomizer` beans, which allow programmatic `SchedulerFactoryBean` customization. NOTE: In particular, an `Executor` bean is not associated with the scheduler as Quartz @@ -6030,6 +6030,15 @@ in a similar manner, as shown in the following example: } ---- +Jobs created by configuration will not overwrite already registered jobs that have been +read in from a persistent job store. To enable overwriting existing job definitions set +`spring.quartz.overwriteExistingJobs` property: + +[source,properties,indent=0] +---- + spring.quartz.overwriteExistingJobs=true +---- + [[boot-features-integration]]