Skip unnecessary attempt at executing Job
...that was already executed as part of the "local" set. Also added some howto docs on executing Batch jobs. See gh-382
This commit is contained in:
parent
3ad6c96ce5
commit
09f3ee14a4
|
@ -912,6 +912,19 @@ scripts can act as "poor man's migrations" - inserts that fail mean
|
|||
that the data is already there, so there would be no need to prevent
|
||||
the application from running, for instance.
|
||||
|
||||
### Spring Batch
|
||||
|
||||
If you are using Spring Batch then it comes pre-packaged with SQL
|
||||
initialization scripts for most popular database platforms. Spring
|
||||
Boot will detect your database type, and execute those scripts by
|
||||
default, and in this case will switch the fail fast setting to false
|
||||
(errors are logged but do not prevent the application from
|
||||
starting). This is because the scripts are known to be reliable and
|
||||
generally do not contain bugs, so errors are ignorable, and ignoring
|
||||
them makes the scripts idempotent. You can switch off the
|
||||
initialization explicitly using
|
||||
`spring.batch.initializer.enabled=false`.
|
||||
|
||||
### Higher Level Migration Tools
|
||||
|
||||
Spring Boot works fine with higher level migration tools
|
||||
|
@ -921,6 +934,31 @@ Flyway because it is easier on the eyes, and it isn't very common to
|
|||
need platform independence: usually only one or at most couple of
|
||||
platforms is needed.
|
||||
|
||||
## Execute Spring Batch Jobs on Startup
|
||||
|
||||
Spring Batch autoconfiguration is enabled by adding
|
||||
`@EnableBatchProcessing` (from Spring Batch) somewhere in your
|
||||
context.
|
||||
|
||||
By default it executes *all* `Jobs` in the application context on
|
||||
startup (see
|
||||
[JobLauncherCommandLineRunner](https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/JobLauncherCommandLineRunner.java)
|
||||
for details). You can narrow down to a specific job or jobs by
|
||||
specifying `spring.batch.job.names` (comma separated job name
|
||||
patterns).
|
||||
|
||||
If the application context includes a `JobRegistry` then
|
||||
the jobs in `spring.batch.job.names` are looked up in the regsitry
|
||||
instead of bein autowired from the context. This is a common pattern
|
||||
with more complex systems where multiple jobs are defined in child
|
||||
contexts and registered centrally.
|
||||
|
||||
See
|
||||
[BatchAutoConfiguration](https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java)
|
||||
and
|
||||
[@EnableBatchProcessing](https://github.com/spring-projects/spring-batch/blob/master/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java)
|
||||
for more details.
|
||||
|
||||
<span id="discover.options"/>
|
||||
## Discover Built-in Options for External Properties
|
||||
|
||||
|
|
|
@ -23,17 +23,20 @@ import java.util.Properties;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
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.JobParametersInvalidException;
|
||||
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;
|
||||
import org.springframework.batch.core.launch.NoSuchJobException;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
@ -63,7 +66,7 @@ public class JobLauncherCommandLineRunner implements CommandLineRunner,
|
|||
|
||||
@Autowired(required = false)
|
||||
private JobRegistry jobRegistry;
|
||||
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
|
||||
|
@ -103,14 +106,12 @@ public class JobLauncherCommandLineRunner implements CommandLineRunner,
|
|||
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);
|
||||
if (this.publisher != null) {
|
||||
this.publisher.publishEvent(new JobExecutionEvent(execution));
|
||||
}
|
||||
if (this.jobs.contains(job)) {
|
||||
continue;
|
||||
}
|
||||
} catch (NoSuchJobException nsje) {
|
||||
execute(job, jobParameters);
|
||||
}
|
||||
catch (NoSuchJobException nsje) {
|
||||
logger.debug("No job found in registry for job name: " + jobName);
|
||||
continue;
|
||||
}
|
||||
|
@ -118,6 +119,20 @@ public class JobLauncherCommandLineRunner implements CommandLineRunner,
|
|||
}
|
||||
}
|
||||
|
||||
protected void execute(Job job, JobParameters jobParameters)
|
||||
throws JobExecutionAlreadyRunningException, JobRestartException,
|
||||
JobInstanceAlreadyCompleteException, JobParametersInvalidException {
|
||||
String jobName = job.getName();
|
||||
JobExecution previousExecution = this.jobRepository.getLastJobExecution(jobName,
|
||||
jobParameters);
|
||||
if (previousExecution == null || previousExecution.getStatus().isUnsuccessful()) {
|
||||
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) {
|
||||
|
@ -128,10 +143,7 @@ public class JobLauncherCommandLineRunner implements CommandLineRunner,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
JobExecution execution = this.jobLauncher.run(job, jobParameters);
|
||||
if (this.publisher != null) {
|
||||
this.publisher.publishEvent(new JobExecutionEvent(execution));
|
||||
}
|
||||
execute(job, jobParameters);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,29 +114,30 @@ public class BatchAutoConfigurationTests {
|
|||
assertNotNull(this.context.getBean(JobRepository.class).getLastJobExecution(
|
||||
"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,
|
||||
this.context.register(NamedJobConfigurationWithRegisteredJob.class,
|
||||
BatchAutoConfiguration.class, EmbeddedDataSourceConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
JobRepository repository = this.context.getBean(JobRepository.class);
|
||||
assertNotNull(this.context.getBean(JobLauncher.class));
|
||||
this.context.getBean(JobLauncherCommandLineRunner.class).run();
|
||||
assertNotNull(this.context.getBean(JobRepository.class).getLastJobExecution(
|
||||
"discreteRegisteredJob", new JobParameters()));
|
||||
assertNotNull(repository.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,
|
||||
this.context.register(NamedJobConfigurationWithLocalJob.class,
|
||||
BatchAutoConfiguration.class, EmbeddedDataSourceConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertNotNull(this.context.getBean(JobLauncher.class));
|
||||
|
@ -206,17 +207,17 @@ public class BatchAutoConfigurationTests {
|
|||
protected static class NamedJobConfigurationWithRegisteredJob {
|
||||
@Autowired
|
||||
private JobRegistry jobRegistry;
|
||||
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
|
||||
|
||||
@Bean
|
||||
public JobRegistryBeanPostProcessor registryProcessor() {
|
||||
JobRegistryBeanPostProcessor processor = new JobRegistryBeanPostProcessor();
|
||||
processor.setJobRegistry(jobRegistry);
|
||||
processor.setJobRegistry(this.jobRegistry);
|
||||
return processor;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Job discreteJob() {
|
||||
AbstractJob job = new AbstractJob("discreteRegisteredJob") {
|
||||
|
@ -241,13 +242,13 @@ public class BatchAutoConfigurationTests {
|
|||
return job;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EnableBatchProcessing
|
||||
protected static class NamedJobConfigurationWithLocalJob {
|
||||
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
|
||||
|
||||
@Bean
|
||||
public Job discreteJob() {
|
||||
AbstractJob job = new AbstractJob("discreteLocalJob") {
|
||||
|
@ -272,7 +273,7 @@ public class BatchAutoConfigurationTests {
|
|||
return job;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EnableBatchProcessing
|
||||
protected static class JobConfiguration {
|
||||
@Autowired
|
||||
|
|
Loading…
Reference in New Issue