Fix @Conditional for Batch command line runner

Previously it was @ConditionalOnMissingBean(CommandLineRunner.class)
which caued obvious problems when user wanted to add an unrelated
CLR.

Extended feature set so that a JobRegistry can also be used (with
spring.batch.job.name) and the whole idea can be switched off with
spring.boot.job.enabled.
This commit is contained in:
Dave Syer 2013-12-11 13:54:35 +00:00
parent a8c69220c7
commit cf05a5d578
3 changed files with 72 additions and 8 deletions

View File

@ -17,17 +17,22 @@
package org.springframework.boot.autoconfigure.batch;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.boot.CommandLineRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Batch.
* {@link EnableAutoConfiguration Auto-configuration} for Spring Batch. By default all
* jobs in the context will be executed on startup (disable this behaviour with
* <code>spring.boot.exec.enabled=false</code>). User can supply a job name to execute on
* startup with <code>spring.batch.exec.name=...</code>.
*
* @author Dave Syer
*/
@ -35,6 +40,9 @@ import org.springframework.context.annotation.Configuration;
@ConditionalOnClass({ JobLauncher.class })
public class BatchAutoConfiguration {
@Value("${spring.batch.job.name:}")
private String jobName;
@Bean
@ConditionalOnMissingBean(BatchDatabaseInitializer.class)
public BatchDatabaseInitializer batchDatabaseInitializer() {
@ -42,10 +50,15 @@ public class BatchAutoConfiguration {
}
@Bean
@ConditionalOnMissingBean(CommandLineRunner.class)
@ConditionalOnMissingBean(JobLauncherCommandLineRunner.class)
@ConditionalOnBean(JobLauncher.class)
@ConditionalOnExpression("${spring.batch.job.enabled:true}")
public JobLauncherCommandLineRunner jobLauncherCommandLineRunner() {
return new JobLauncherCommandLineRunner();
JobLauncherCommandLineRunner runner = new JobLauncherCommandLineRunner();
if (StringUtils.hasText(this.jobName)) {
runner.setJobName(this.jobName);
}
return runner;
}
@Bean

View File

@ -26,6 +26,8 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionException;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
import org.springframework.batch.core.converter.JobParametersConverter;
import org.springframework.batch.core.launch.JobLauncher;
@ -34,10 +36,13 @@ import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils;
/**
* {@link CommandLineRunner} to {@link JobLauncher launch} Spring Batch jobs.
* {@link CommandLineRunner} to {@link JobLauncher launch} Spring Batch jobs. Runs all
* jobs in the surrounding context by default. Can also be used to launch a specific job
* by providing a jobName
*
* @author Dave Syer
*/
@ -53,11 +58,20 @@ public class JobLauncherCommandLineRunner implements CommandLineRunner,
@Autowired
private JobLauncher jobLauncher;
@Autowired(required = false)
private JobRegistry jobRegistry;
private String jobName;
@Autowired(required = false)
private Collection<Job> jobs = Collections.emptySet();
private ApplicationEventPublisher publisher;
public void setJobName(String jobName) {
this.jobName = jobName;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
@ -71,12 +85,36 @@ public class JobLauncherCommandLineRunner implements CommandLineRunner,
protected void launchJobFromProperties(Properties properties)
throws JobExecutionException {
for (Job job : this.jobs) {
JobExecution execution = this.jobLauncher.run(job,
this.converter.getJobParameters(properties));
JobParameters jobParameters = this.converter.getJobParameters(properties);
executeRegisteredJobs(jobParameters);
executeLocalJobs(jobParameters);
}
private void executeRegisteredJobs(JobParameters jobParameters)
throws JobExecutionException {
if (this.jobRegistry != null && StringUtils.hasText(this.jobName)) {
Job job = this.jobRegistry.getJob(this.jobName);
JobExecution execution = this.jobLauncher.run(job, jobParameters);
if (this.publisher != null) {
this.publisher.publishEvent(new JobExecutionEvent(execution));
}
}
}
private void executeLocalJobs(JobParameters jobParameters)
throws JobExecutionException {
for (Job job : this.jobs) {
if (StringUtils.hasText(this.jobName)) {
if (!PatternMatchUtils.simpleMatch(this.jobName, job.getName())) {
logger.debug("Skipped job: " + job.getName());
continue;
}
}
JobExecution execution = this.jobLauncher.run(job, jobParameters);
if (this.publisher != null) {
this.publisher.publishEvent(new JobExecutionEvent(execution));
}
}
}
}

View File

@ -36,6 +36,7 @@ import org.springframework.batch.core.job.AbstractJob;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.TestUtils;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
@ -91,6 +92,18 @@ public class BatchAutoConfigurationTests {
"job", new JobParameters()));
}
@Test
public void testDisableLaunchesJob() throws Exception {
this.context = new AnnotationConfigApplicationContext();
TestUtils.addEnviroment(this.context, "spring.batch.job.enabled:false");
this.context.register(JobConfiguration.class, BatchAutoConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(JobLauncher.class));
assertEquals(0, this.context.getBeanNamesForType(CommandLineRunner.class).length);
}
@Test
public void testDisableSchemaLoader() throws Exception {
this.context = new AnnotationConfigApplicationContext();