From c38cd7454238a2fc3563fbe65b2880bbd8724d85 Mon Sep 17 00:00:00 2001 From: Akshay Dubey <38462415+itsAkshayDubey@users.noreply.github.com> Date: Sat, 24 Jun 2023 14:02:29 +0000 Subject: [PATCH] Fail fast if job name does not exist See gh-36060 --- .../batch/JobLauncherApplicationRunner.java | 31 ++++++++++++++----- .../batch/BatchAutoConfigurationTests.java | 12 +++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/JobLauncherApplicationRunner.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/JobLauncherApplicationRunner.java index 76b3e955d2..dd6baf6865 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/JobLauncherApplicationRunner.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/JobLauncherApplicationRunner.java @@ -24,6 +24,8 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; +import javax.annotation.PostConstruct; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -66,6 +68,7 @@ import org.springframework.util.StringUtils; * @author Jean-Pierre Bergamin * @author Mahmoud Ben Hassine * @author Stephane Nicoll + * @author Akshay Dubey * @since 2.3.0 */ public class JobLauncherApplicationRunner implements ApplicationRunner, Ordered, ApplicationEventPublisherAware { @@ -111,6 +114,18 @@ public class JobLauncherApplicationRunner implements ApplicationRunner, Ordered, this.jobRepository = jobRepository; } + @PostConstruct + public void validate() { + if (StringUtils.hasText(this.jobNames)) { + String[] jobsToRun = this.jobNames.split(","); + for(String jobName: jobsToRun) { + if (!isLocalJob(jobName) && !isRegisteredJob(jobName)) { + throw new IllegalArgumentException("No job instances were found for job name [" + jobName + "]"); + } + } + } + } + public void setOrder(int order) { this.order = order; } @@ -161,6 +176,14 @@ public class JobLauncherApplicationRunner implements ApplicationRunner, Ordered, executeRegisteredJobs(jobParameters); } + private boolean isLocalJob(String jobName) { + return this.jobs.stream().anyMatch((job) -> job.getName().equals(jobName)); + } + + private boolean isRegisteredJob(String jobName) { + return this.jobRegistry != null && this.jobRegistry.getJobNames().contains(jobName); + } + private void executeLocalJobs(JobParameters jobParameters) throws JobExecutionException { for (Job job : this.jobs) { if (StringUtils.hasText(this.jobNames)) { @@ -178,16 +201,10 @@ public class JobLauncherApplicationRunner implements ApplicationRunner, Ordered, if (this.jobRegistry != null && StringUtils.hasText(this.jobNames)) { String[] jobsToRun = this.jobNames.split(","); for (String jobName : jobsToRun) { - try { + if(isRegisteredJob(jobName) && !isLocalJob(jobName)) { Job job = this.jobRegistry.getJob(jobName); - if (this.jobs.contains(job)) { - continue; - } execute(job, jobParameters); } - catch (NoSuchJobException ex) { - logger.debug(LogMessage.format("No job found in registry for job name: %s", jobName)); - } } } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java index 6b1062e41b..a25e7190b5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java @@ -80,6 +80,7 @@ import static org.mockito.Mockito.mock; * @author Stephane Nicoll * @author Vedran Pavic * @author Kazuki Shimizu + * @author Akshay Dubey */ @ExtendWith(OutputCaptureExtension.class) class BatchAutoConfigurationTests { @@ -374,6 +375,17 @@ class BatchAutoConfigurationTests { .hasBean("customInitializer")); } + @Test + void testNonConfiguredJobThrowsException() { + this.contextRunner + .withUserConfiguration(NamedJobConfigurationWithLocalJob.class, EmbeddedDataSourceConfiguration.class) + .withPropertyValues("spring.batch.job.names:discreteLocalJob,nonConfiguredJob") + .run((context) -> { + assertThat(context).hasFailed().getFailure().getRootCause() + .hasMessageContaining("nonConfiguredJob"); + }); + } + @Configuration(proxyBeanMethods = false) protected static class BatchDataSourceConfiguration {