Adding support for multiple configured job names

pull/365/head
hoserdude 11 years ago committed by Dave Syer
parent 08d8cb8efd
commit 3ad6c96ce5

@ -44,10 +44,14 @@ import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Batch. By default all * {@link EnableAutoConfiguration Auto-configuration} for Spring Batch. By default a Runner
* jobs in the context will be executed on startup (disable this behaviour with * will be created and all jobs in the context will be executed on startup.
* <code>spring.boot.exec.enabled=false</code>). User can supply a job name to execute on *
* startup with <code>spring.batch.exec.name=...</code>. * Disable this behaviour with <code>spring.batch.job.enabled=false</code>).
*
* Alternatively, discrete Job names to execute on startup can be supplied by the User with
* a comma-delimited list: <code>spring.batch.job.names=job1,job2</code>. In this case the
* Runner will first find jobs registered as Beans, then those in the existing JobRegistry.
* *
* @author Dave Syer * @author Dave Syer
*/ */
@ -57,8 +61,8 @@ import org.springframework.util.StringUtils;
@ConditionalOnBean(JobLauncher.class) @ConditionalOnBean(JobLauncher.class)
public class BatchAutoConfiguration { public class BatchAutoConfiguration {
@Value("${spring.batch.job.name:}") @Value("${spring.batch.job.names:}")
private String jobName; private String jobNames;
@Autowired(required = false) @Autowired(required = false)
private JobParametersConverter jobParametersConverter; private JobParametersConverter jobParametersConverter;
@ -74,8 +78,8 @@ public class BatchAutoConfiguration {
@ConditionalOnExpression("${spring.batch.job.enabled:true}") @ConditionalOnExpression("${spring.batch.job.enabled:true}")
public JobLauncherCommandLineRunner jobLauncherCommandLineRunner() { public JobLauncherCommandLineRunner jobLauncherCommandLineRunner() {
JobLauncherCommandLineRunner runner = new JobLauncherCommandLineRunner(); JobLauncherCommandLineRunner runner = new JobLauncherCommandLineRunner();
if (StringUtils.hasText(this.jobName)) { if (StringUtils.hasText(this.jobNames)) {
runner.setJobName(this.jobName); runner.setJobNames(this.jobNames);
} }
return runner; return runner;
} }

@ -23,6 +23,7 @@ import java.util.Properties;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.Job; import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionException; import org.springframework.batch.core.JobExecutionException;
@ -31,6 +32,8 @@ import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.converter.DefaultJobParametersConverter; import org.springframework.batch.core.converter.DefaultJobParametersConverter;
import org.springframework.batch.core.converter.JobParametersConverter; import org.springframework.batch.core.converter.JobParametersConverter;
import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
@ -61,15 +64,18 @@ public class JobLauncherCommandLineRunner implements CommandLineRunner,
@Autowired(required = false) @Autowired(required = false)
private JobRegistry jobRegistry; private JobRegistry jobRegistry;
private String jobName; @Autowired
private JobRepository jobRepository;
private String jobNames;
@Autowired(required = false) @Autowired(required = false)
private final Collection<Job> jobs = Collections.emptySet(); private final Collection<Job> jobs = Collections.emptySet();
private ApplicationEventPublisher publisher; private ApplicationEventPublisher publisher;
public void setJobName(String jobName) { public void setJobNames(String jobNames) {
this.jobName = jobName; this.jobNames = jobNames;
} }
@Override @Override
@ -86,26 +92,38 @@ public class JobLauncherCommandLineRunner implements CommandLineRunner,
protected void launchJobFromProperties(Properties properties) protected void launchJobFromProperties(Properties properties)
throws JobExecutionException { throws JobExecutionException {
JobParameters jobParameters = this.converter.getJobParameters(properties); JobParameters jobParameters = this.converter.getJobParameters(properties);
executeRegisteredJobs(jobParameters);
executeLocalJobs(jobParameters); executeLocalJobs(jobParameters);
executeRegisteredJobs(jobParameters);
} }
private void executeRegisteredJobs(JobParameters jobParameters) private void executeRegisteredJobs(JobParameters jobParameters)
throws JobExecutionException { throws JobExecutionException {
if (this.jobRegistry != null && StringUtils.hasText(this.jobName)) { if (this.jobRegistry != null && StringUtils.hasText(this.jobNames)) {
Job job = this.jobRegistry.getJob(this.jobName); String[] jobsToRun = this.jobNames.split(",");
for (String jobName : jobsToRun) {
try {
Job job = this.jobRegistry.getJob(jobName);
JobExecution previousExecution = jobRepository.getLastJobExecution(jobName, jobParameters);
if (previousExecution == null || previousExecution.getStatus() != BatchStatus.COMPLETED) {
JobExecution execution = this.jobLauncher.run(job, jobParameters); JobExecution execution = this.jobLauncher.run(job, jobParameters);
if (this.publisher != null) { if (this.publisher != null) {
this.publisher.publishEvent(new JobExecutionEvent(execution)); this.publisher.publishEvent(new JobExecutionEvent(execution));
} }
} }
} catch (NoSuchJobException nsje) {
logger.debug("No job found in registry for job name: " + jobName);
continue;
}
}
}
} }
private void executeLocalJobs(JobParameters jobParameters) private void executeLocalJobs(JobParameters jobParameters)
throws JobExecutionException { throws JobExecutionException {
for (Job job : this.jobs) { for (Job job : this.jobs) {
if (StringUtils.hasText(this.jobName)) { if (StringUtils.hasText(this.jobNames)) {
if (!PatternMatchUtils.simpleMatch(this.jobName, job.getName())) { String[] jobsToRun = this.jobNames.split(",");
if (!PatternMatchUtils.simpleMatch(jobsToRun, job.getName())) {
logger.debug("Skipped job: " + job.getName()); logger.debug("Skipped job: " + job.getName());
continue; continue;
} }

@ -32,7 +32,9 @@ import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionException; import org.springframework.batch.core.JobExecutionException;
import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step; import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor;
import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.job.AbstractJob; import org.springframework.batch.core.job.AbstractJob;
import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.JobLauncher;
@ -113,6 +115,36 @@ public class BatchAutoConfigurationTests {
"job", new JobParameters())); "job", new JobParameters()));
} }
@Test
public void testDefinesAndLaunchesNamedJob() throws Exception {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.batch.job.names:discreteRegisteredJob");
this.context.register(NamedJobConfigurationWithRegisteredJob.class, BatchAutoConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(JobLauncher.class));
this.context.getBean(JobLauncherCommandLineRunner.class).run();
assertNotNull(this.context.getBean(JobRepository.class).getLastJobExecution(
"discreteRegisteredJob", new JobParameters()));
}
@Test
public void testDefinesAndLaunchesLocalJob() throws Exception {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.batch.job.names:discreteLocalJob");
this.context.register(NamedJobConfigurationWithLocalJob.class, BatchAutoConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertNotNull(this.context.getBean(JobLauncher.class));
this.context.getBean(JobLauncherCommandLineRunner.class).run();
assertNotNull(this.context.getBean(JobRepository.class).getLastJobExecution(
"discreteLocalJob", new JobParameters()));
}
@Test @Test
public void testDisableLaunchesJob() throws Exception { public void testDisableLaunchesJob() throws Exception {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
@ -170,6 +202,77 @@ public class BatchAutoConfigurationTests {
protected static class TestConfiguration { protected static class TestConfiguration {
} }
@EnableBatchProcessing
protected static class NamedJobConfigurationWithRegisteredJob {
@Autowired
private JobRegistry jobRegistry;
@Autowired
private JobRepository jobRepository;
@Bean
public JobRegistryBeanPostProcessor registryProcessor() {
JobRegistryBeanPostProcessor processor = new JobRegistryBeanPostProcessor();
processor.setJobRegistry(jobRegistry);
return processor;
}
@Bean
public Job discreteJob() {
AbstractJob job = new AbstractJob("discreteRegisteredJob") {
@Override
public Collection<String> getStepNames() {
return Collections.emptySet();
}
@Override
public Step getStep(String stepName) {
return null;
}
@Override
protected void doExecute(JobExecution execution)
throws JobExecutionException {
execution.setStatus(BatchStatus.COMPLETED);
}
};
job.setJobRepository(this.jobRepository);
return job;
}
}
@EnableBatchProcessing
protected static class NamedJobConfigurationWithLocalJob {
@Autowired
private JobRepository jobRepository;
@Bean
public Job discreteJob() {
AbstractJob job = new AbstractJob("discreteLocalJob") {
@Override
public Collection<String> getStepNames() {
return Collections.emptySet();
}
@Override
public Step getStep(String stepName) {
return null;
}
@Override
protected void doExecute(JobExecution execution)
throws JobExecutionException {
execution.setStatus(BatchStatus.COMPLETED);
}
};
job.setJobRepository(this.jobRepository);
return job;
}
}
@EnableBatchProcessing @EnableBatchProcessing
protected static class JobConfiguration { protected static class JobConfiguration {
@Autowired @Autowired

Loading…
Cancel
Save