Update documentation
This commit is contained in:
@@ -74,8 +74,8 @@ The following example shows how to register a listener with a step Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step simpleStep() {
|
||||
return this.stepBuilderFactory.get("simpleStep")
|
||||
public Step simpleStep(JobRepository jobRepository) {
|
||||
return new StepBuilder("simpleStep", jobRepository)
|
||||
...
|
||||
.listener(new ItemFailureLoggerListener())
|
||||
.build();
|
||||
@@ -163,9 +163,9 @@ The following example shows how to inject a completion policy into a step in Jav
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step simpleStep() {
|
||||
return this.stepBuilderFactory.get("simpleStep")
|
||||
.<String, String>chunk(new SpecialCompletionPolicy())
|
||||
public Step simpleStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("simpleStep", jobRepository)
|
||||
.<String, String>chunk(new SpecialCompletionPolicy(), transactionManager)
|
||||
.reader(reader())
|
||||
.writer(writer())
|
||||
.build();
|
||||
@@ -724,17 +724,17 @@ The following example shows how to promote a step to the `Job` `ExecutionContext
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job1() {
|
||||
return this.jobBuilderFactory.get("job1")
|
||||
public Job job1(JobRepository jobRepository) {
|
||||
return new JobBuilder("job1", jobRepository)
|
||||
.start(step1())
|
||||
.next(step1())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(10)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(reader())
|
||||
.writer(savingWriter())
|
||||
.listener(promotionListener())
|
||||
|
||||
@@ -72,8 +72,8 @@ example shows:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job footballJob() {
|
||||
return this.jobBuilderFactory.get("footballJob")
|
||||
public Job footballJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("footballJob", jobRepository)
|
||||
.start(playerLoad())
|
||||
.next(gameLoad())
|
||||
.next(playerSummarization())
|
||||
@@ -111,8 +111,8 @@ instantiation of a `Job`, as the following example shows:
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public Job footballJob() {
|
||||
return this.jobBuilderFactory.get("footballJob")
|
||||
public Job footballJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("footballJob", jobRepository)
|
||||
.start(playerLoad())
|
||||
.next(gameLoad())
|
||||
.next(playerSummarization())
|
||||
|
||||
@@ -36,8 +36,8 @@ The following example creates a `footballJob`:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job footballJob() {
|
||||
return this.jobBuilderFactory.get("footballJob")
|
||||
public Job footballJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("footballJob", jobRepository)
|
||||
.start(playerLoad())
|
||||
.next(gameLoad())
|
||||
.next(playerSummarization())
|
||||
@@ -106,8 +106,8 @@ namespace (for XML-based configuration). The following example shows both Java a
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public Job footballJob() {
|
||||
return this.jobBuilderFactory.get("footballJob")
|
||||
public Job footballJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("footballJob", jobRepository)
|
||||
.start(playerLoad())
|
||||
.next(gameLoad())
|
||||
.next(playerSummarization())
|
||||
@@ -184,8 +184,8 @@ The following example shows how to set the `restartable` field to `false` in Jav
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job footballJob() {
|
||||
return this.jobBuilderFactory.get("footballJob")
|
||||
public Job footballJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("footballJob", jobRepository)
|
||||
.preventRestart()
|
||||
...
|
||||
.build();
|
||||
@@ -274,8 +274,8 @@ The following example shows how to add a listener method to a Java job definitio
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job footballJob() {
|
||||
return this.jobBuilderFactory.get("footballJob")
|
||||
public Job footballJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("footballJob", jobRepository)
|
||||
.listener(sampleListener())
|
||||
...
|
||||
.build();
|
||||
@@ -390,8 +390,8 @@ The configuration of a validator is supported through the Java builders:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job1() {
|
||||
return this.jobBuilderFactory.get("job1")
|
||||
public Job job1(JobRepository jobRepository) {
|
||||
return new JobBuilder("job1", jobRepository)
|
||||
.validator(parametersValidator())
|
||||
...
|
||||
.build();
|
||||
@@ -408,8 +408,8 @@ The configuration of a validator is supported through the Java builders, as foll
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public Job job1() {
|
||||
return this.jobBuilderFactory.get("job1")
|
||||
public Job job1(JobRepository jobRepository) {
|
||||
return tnew JobBuilder("job1", jobRepository)
|
||||
.validator(parametersValidator())
|
||||
...
|
||||
.build();
|
||||
@@ -444,37 +444,46 @@ annotation and two builders.
|
||||
|
||||
The `@EnableBatchProcessing` annotation works similarly to the other `@Enable*` annotations in the
|
||||
Spring family. In this case, `@EnableBatchProcessing` provides a base configuration for
|
||||
building batch jobs. Within this base configuration, an instance of `StepScope` is
|
||||
building batch jobs. Within this base configuration, an instance of `StepScope` and `Jobscope` are
|
||||
created, in addition to a number of beans being made available to be autowired:
|
||||
|
||||
* `JobRepository`: a bean named `jobRepository`
|
||||
* `JobLauncher`: a bean named `jobLauncher`
|
||||
* `JobRegistry`: a bean named `jobRegistry`
|
||||
* `PlatformTransactionManager`: a bean named `transactionManager`
|
||||
* `JobBuilderFactory`: a bean named `jobBuilders`
|
||||
* `StepBuilderFactory`: a bean named `stepBuilders`
|
||||
* `JobExplorer`: a bean named `jobExplorer`
|
||||
|
||||
The core interface for this configuration is the `BatchConfigurer`. The default
|
||||
implementation provides the beans mentioned in the preceding list and requires a `DataSource`
|
||||
to be provided as a bean within the context. This data source is used by the `JobRepository` instance.
|
||||
You can customize any of these beans
|
||||
by creating a custom implementation of the `BatchConfigurer` interface.
|
||||
Typically, extending the `DefaultBatchConfigurer` (which is provided if a
|
||||
`BatchConfigurer` is not found) and overriding the required getter is sufficient.
|
||||
However, you may need to implement your own from scratch. The following
|
||||
example shows how to provide a custom transaction manager:
|
||||
The default implementation provides the beans mentioned in the preceding list and requires a `DataSource`
|
||||
and a `PlatformTransactionManager` to be provided as beans within the context. The data source and transaction
|
||||
manager are used by the `JobRepository` and `JobExplorer` instances. By default, the data source named `dataSource`
|
||||
and the transaction manager named `transactionManager` will be used. You can customize any of these beans by using
|
||||
the attributes of the `@EnableBatchProcessing` annotation. The following example shows how to provide a
|
||||
custom data source and transaction manager:
|
||||
|
||||
====
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public BatchConfigurer batchConfigurer(DataSource dataSource) {
|
||||
return new DefaultBatchConfigurer(dataSource) {
|
||||
@Override
|
||||
public PlatformTransactionManager getTransactionManager() {
|
||||
return new MyTransactionManager();
|
||||
}
|
||||
};
|
||||
@Configuration
|
||||
@EnableBatchProcessing(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager")
|
||||
public class MyJobConfiguration {
|
||||
|
||||
@Bean
|
||||
public DataSource batchDataSource() {
|
||||
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
|
||||
.addScript("/org/springframework/batch/core/schema-hsqldb.sql")
|
||||
.generateUniqueName(true).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JdbcTransactionManager batchTransactionManager(DataSource dataSource) {
|
||||
return new JdbcTransactionManager(dataSource);
|
||||
}
|
||||
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("myJob", jobRepository)
|
||||
//define job flow as needed
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -485,51 +494,62 @@ Only one configuration class needs to have the `@EnableBatchProcessing` annotati
|
||||
you have a class annotated with it, you have all of the configuration described earlier.
|
||||
====
|
||||
|
||||
With the base configuration in place, you can use the provided builder factories to
|
||||
configure a job. The following example shows a two-step job configured with the
|
||||
`JobBuilderFactory` and the `StepBuilderFactory`:
|
||||
Starting from v5.0, an alternative, programmatic way of configuring base infrastrucutre beans
|
||||
is provided through the `DefaultBatchConfiguration` class. This class provides the same beans
|
||||
provided by `@EnableBatchProcessing` and can be used as a base class to configure batch jobs.
|
||||
The following snippet is a typical example of how to use it:
|
||||
|
||||
====
|
||||
[source, java]
|
||||
----
|
||||
@Configuration
|
||||
@EnableBatchProcessing
|
||||
@Import(DataSourceConfiguration.class)
|
||||
public class AppConfig {
|
||||
class MyJobConfiguration extends DefaultBatchConfiguration {
|
||||
|
||||
@Autowired
|
||||
private JobBuilderFactory jobs;
|
||||
@Bean
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
// define job flow as needed
|
||||
.build();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private StepBuilderFactory steps;
|
||||
|
||||
@Bean
|
||||
public Job job(@Qualifier("step1") Step step1, @Qualifier("step2") Step step2) {
|
||||
return jobs.get("myJob").start(step1).next(step2).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected Step step1(ItemReader<Person> reader,
|
||||
ItemProcessor<Person, Person> processor,
|
||||
ItemWriter<Person> writer) {
|
||||
return steps.get("step1")
|
||||
.<Person, Person> chunk(10)
|
||||
.reader(reader)
|
||||
.processor(processor)
|
||||
.writer(writer)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected Step step2(Tasklet tasklet) {
|
||||
return steps.get("step2")
|
||||
.tasklet(tasklet)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The data source and transaction manager will be resolved from the application context
|
||||
and set on the job repository and job explorer. You can customize the configuration
|
||||
of any infrastructure bean by overriding the required setter. The following example
|
||||
shows how to customize the character encoding for instance:
|
||||
|
||||
====
|
||||
[source, java]
|
||||
----
|
||||
@Configuration
|
||||
class MyJobConfiguration extends DefaultBatchConfiguration {
|
||||
|
||||
@Bean
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
// define job flow as needed
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Charset getCharset() {
|
||||
return StandardCharsets.ISO_8859_1;
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
`@EnableBatchProcessing` should *not* be used with `DefaultBatchConfiguration`. You should
|
||||
either use the declarative way of configuring Spring Batch through `@EnableBatchProcessing`,
|
||||
or use the programmatic way of extending `DefaultBatchConfiguration`, but not both ways at
|
||||
the same time.
|
||||
====
|
||||
|
||||
[[configuringJobRepository]]
|
||||
=== Configuring a JobRepository
|
||||
|
||||
@@ -538,10 +558,8 @@ When using `@EnableBatchProcessing`, a `JobRepository` is provided for you.
|
||||
This section describes how to configure your own.
|
||||
|
||||
As described earlier, the <<job.adoc#configureJob,`JobRepository`>> is used for basic CRUD operations of the various persisted
|
||||
domain objects within Spring Batch, such as
|
||||
`JobExecution` and
|
||||
`StepExecution`. It is required by many of the major
|
||||
framework features, such as the `JobLauncher`,
|
||||
domain objects within Spring Batch, such as `JobExecution` and `StepExecution`.
|
||||
It is required by many of the major framework features, such as the `JobLauncher`,
|
||||
`Job`, and `Step`.
|
||||
|
||||
[role="xmlContent"]
|
||||
@@ -569,32 +587,6 @@ The `max-varchar-length` defaults to `2500`, which is the length of the long
|
||||
`VARCHAR` columns in the <<schema-appendix.adoc#metaDataSchemaOverview,sample schema
|
||||
scripts>>.
|
||||
|
||||
[role="javaContent"]
|
||||
When you use Java configuration, a `JobRepository` is provided for you. A JDBC-based one is
|
||||
provided if a `DataSource` is provided, and the `Map`-based one is provided if no `DataSource` is provided. However,
|
||||
you can customize the configuration of the `JobRepository` through an implementation of the
|
||||
`BatchConfigurer` interface, as the following example shows:
|
||||
|
||||
.Java Configuration
|
||||
====
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
...
|
||||
// This would reside in your BatchConfigurer implementation
|
||||
@Override
|
||||
protected JobRepository createJobRepository() throws Exception {
|
||||
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setTransactionManager(transactionManager);
|
||||
factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");
|
||||
factory.setTablePrefix("BATCH_");
|
||||
factory.setMaxVarCharLength(1000);
|
||||
return factory.getObject();
|
||||
}
|
||||
...
|
||||
----
|
||||
====
|
||||
|
||||
[role="javaContent"]
|
||||
Other than the `dataSource` and the `transactionManager`, none of the configuration options listed earlier are required.
|
||||
If they are not set, the defaults shown earlier
|
||||
@@ -637,19 +629,17 @@ The following example shows how to override the isolation level in Java:
|
||||
====
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
// This would reside in your BatchConfigurer implementation
|
||||
@Override
|
||||
protected JobRepository createJobRepository() throws Exception {
|
||||
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setTransactionManager(transactionManager);
|
||||
factory.setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ");
|
||||
return factory.getObject();
|
||||
@Configuration
|
||||
@EnableBatchProcessing(isolationLevelForCreate = "ISOLATION_REPEATABLE_READ")
|
||||
public class MyJobConfiguration {
|
||||
|
||||
// job definition
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
If the namespace or factory beans are not used, you must also configure the
|
||||
If the namespace is not used, you must also configure the
|
||||
transactional behavior of the repository by using AOP.
|
||||
|
||||
[role="xmlContent"]
|
||||
@@ -727,14 +717,12 @@ The following example shows how to change the table prefix in Java:
|
||||
====
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
// This would reside in your BatchConfigurer implementation
|
||||
@Override
|
||||
protected JobRepository createJobRepository() throws Exception {
|
||||
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setTransactionManager(transactionManager);
|
||||
factory.setTablePrefix("SYSTEM.TEST_");
|
||||
return factory.getObject();
|
||||
@Configuration
|
||||
@EnableBatchProcessing(tablePrefix = "SYSTEM.TEST_")
|
||||
public class MyJobConfiguration {
|
||||
|
||||
// job definition
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -778,9 +766,8 @@ to the closest match in Java:
|
||||
====
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
// This would reside in your BatchConfigurer implementation
|
||||
@Override
|
||||
protected JobRepository createJobRepository() throws Exception {
|
||||
@Bean
|
||||
public JobRepository jobRepository() throws Exception {
|
||||
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setDatabaseType("db2");
|
||||
@@ -835,9 +822,8 @@ The following example shows a `TaskExecutorJobLauncher` in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
...
|
||||
// This would reside in your BatchConfigurer implementation
|
||||
@Override
|
||||
protected JobLauncher createJobLauncher() throws Exception {
|
||||
@Bean
|
||||
public JobLauncher jobLauncher() throws Exception {
|
||||
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
|
||||
jobLauncher.setJobRepository(jobRepository);
|
||||
jobLauncher.afterPropertiesSet();
|
||||
@@ -1057,23 +1043,17 @@ The following example shows a sample configuration for `endOfDay` in Java:
|
||||
@EnableBatchProcessing
|
||||
public class EndOfDayJobConfiguration {
|
||||
|
||||
@Autowired
|
||||
private JobBuilderFactory jobBuilderFactory;
|
||||
|
||||
@Autowired
|
||||
private StepBuilderFactory stepBuilderFactory;
|
||||
|
||||
@Bean
|
||||
public Job endOfDay() {
|
||||
return this.jobBuilderFactory.get("endOfDay")
|
||||
.start(step1())
|
||||
public Job endOfDay(JobRepository jobRepository, Step step1) {
|
||||
return new JobBuilder("endOfDay", jobRepository)
|
||||
.start(step1)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.tasklet((contribution, chunkContext) -> null)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("step1", jobRepository)
|
||||
.tasklet((contribution, chunkContext) -> null, transactionManager)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1120,25 +1100,19 @@ The following example shows a sample configuration for `endOfDay` in Java:
|
||||
@EnableBatchProcessing
|
||||
public class EndOfDayJobConfiguration {
|
||||
|
||||
@Autowired
|
||||
private JobBuilderFactory jobBuilderFactory;
|
||||
|
||||
@Autowired
|
||||
private StepBuilderFactory stepBuilderFactory;
|
||||
@Bean
|
||||
public Job endOfDay(JobRepository jobRepository, Step step1) {
|
||||
return new JobBuilder("endOfDay", jobRepository)
|
||||
.start(step1)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Job endOfDay() {
|
||||
return this.jobBuilderFactory.get("endOfDay")
|
||||
.start(step1())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.tasklet((contribution, chunkContext) -> null)
|
||||
.build();
|
||||
}
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("step1", jobRepository)
|
||||
.tasklet((contribution, chunkContext) -> null, transactionManager)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -1738,8 +1712,8 @@ For jobs defined in Java, you can associate an incrementer with a `Job` through
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job footballJob() {
|
||||
return this.jobBuilderFactory.get("footballJob")
|
||||
public Job footballJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("footballJob", jobRepository)
|
||||
.incrementer(sampleIncrementer())
|
||||
...
|
||||
.build();
|
||||
@@ -1768,8 +1742,8 @@ The Java configuration builders also provide facilities for the configuration of
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public Job footballJob() {
|
||||
return this.jobBuilderFactory.get("footballJob")
|
||||
public Job footballJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("footballJob", jobRepository)
|
||||
.incrementer(sampleIncrementer())
|
||||
...
|
||||
.build();
|
||||
|
||||
@@ -107,16 +107,16 @@ objects, throwing an exception if any other type is provided. Similarly, the
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job ioSampleJob() {
|
||||
return this.jobBuilderFactory.get("ioSampleJob")
|
||||
public Job ioSampleJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("ioSampleJob", jobRepository)
|
||||
.start(step1())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<Foo, Bar>chunk(2)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("step1", jobRepository)
|
||||
.<Foo, Bar>chunk(2, transactionManager)
|
||||
.reader(fooReader())
|
||||
.processor(fooProcessor())
|
||||
.writer(barWriter())
|
||||
@@ -212,16 +212,16 @@ Just as with the previous example, you can configure the composite processor int
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job ioSampleJob() {
|
||||
return this.jobBuilderFactory.get("ioSampleJob")
|
||||
public Job ioSampleJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("ioSampleJob", jobRepository)
|
||||
.start(step1())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<Foo, Foobar>chunk(2)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<Foo, Foobar>chunk(2, transactionManager)
|
||||
.reader(fooReader())
|
||||
.processor(compositeProcessor())
|
||||
.writer(foobarWriter())
|
||||
|
||||
@@ -175,16 +175,16 @@ The following example shows how to inject a delegate as a stream in XML:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job ioSampleJob() {
|
||||
return this.jobBuilderFactory.get("ioSampleJob")
|
||||
public Job ioSampleJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("ioSampleJob", jobRepository)
|
||||
.start(step1())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(2)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(2, transactionManager)
|
||||
.reader(fooReader())
|
||||
.processor(fooProcessor())
|
||||
.writer(compositeItemWriter())
|
||||
|
||||
@@ -62,9 +62,9 @@ public TaskExecutor taskExecutor() {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step sampleStep(TaskExecutor taskExecutor) {
|
||||
return this.stepBuilderFactory.get("sampleStep")
|
||||
.<String, String>chunk(10)
|
||||
public Step sampleStep(TaskExecutor taskExecutor, JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("sampleStep", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.taskExecutor(taskExecutor)
|
||||
@@ -106,9 +106,9 @@ follows:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step sampleStep(TaskExecutor taskExecutor) {
|
||||
return this.stepBuilderFactory.get("sampleStep")
|
||||
.<String, String>chunk(10)
|
||||
public Step sampleStep(TaskExecutor taskExecutor, JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("sampleStep", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.taskExecutor(taskExecutor)
|
||||
@@ -179,8 +179,8 @@ is straightforward, as follows:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(splitFlow())
|
||||
.next(step4())
|
||||
.build() //builds FlowJobBuilder instance
|
||||
|
||||
@@ -520,8 +520,8 @@ The following example shows the how to add a step-level listener in Java:
|
||||
.Java Configuration
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
public Job importPaymentsJob() {
|
||||
return jobBuilderFactory.get("importPayments")
|
||||
public Job importPaymentsJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("importPayments", jobRepository)
|
||||
.start(stepBuilderFactory.get("step1")
|
||||
.chunk(200)
|
||||
.listener(notificationExecutionsListener())
|
||||
@@ -673,8 +673,8 @@ following in Java:
|
||||
.Java Configuration
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
public Job chunkJob() {
|
||||
return jobBuilderFactory.get("personJob")
|
||||
public Job chunkJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("personJob", jobRepository)
|
||||
.start(stepBuilderFactory.get("step1")
|
||||
.<Person, Person>chunk(200)
|
||||
.reader(itemReader())
|
||||
@@ -1230,8 +1230,8 @@ Java:
|
||||
.Java Configuration
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
public Job personJob() {
|
||||
return jobBuilderFactory.get("personJob")
|
||||
public Job personJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("personJob", jobRepository)
|
||||
.start(stepBuilderFactory.get("step1.manager")
|
||||
.partitioner("step1.worker", partitioner())
|
||||
.partitionHandler(partitionHandler())
|
||||
|
||||
@@ -120,8 +120,7 @@ following example shows:
|
||||
*/
|
||||
@Bean
|
||||
public Job sampleJob(JobRepository jobRepository, Step sampleStep) {
|
||||
return this.jobBuilderFactory.get("sampleJob")
|
||||
.repository(jobRepository)
|
||||
return new JobBuilder("sampleJob", jobRepository)
|
||||
.start(sampleStep)
|
||||
.build();
|
||||
}
|
||||
@@ -131,10 +130,9 @@ public Job sampleJob(JobRepository jobRepository, Step sampleStep) {
|
||||
* configured
|
||||
*/
|
||||
@Bean
|
||||
public Step sampleStep(PlatformTransactionManager transactionManager) {
|
||||
return this.stepBuilderFactory.get("sampleStep")
|
||||
.transactionManager(transactionManager)
|
||||
.<String, String>chunk(10)
|
||||
public Step sampleStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("sampleStep", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.build();
|
||||
@@ -182,9 +180,9 @@ Note that `job-repository` defaults to `jobRepository` and
|
||||
optional, since the item could be directly passed from the reader to the writer.
|
||||
|
||||
[role="javaContent"]
|
||||
Note that `repository` defaults to `jobRepository` and `transactionManager`
|
||||
defaults to `transactionManager` (all provided through the infrastructure from
|
||||
`@EnableBatchProcessing`). Also, the `ItemProcessor` is optional, since the item could be
|
||||
Note that `repository` defaults to `jobRepository` (provided through `@EnableBatchProcessing`)
|
||||
and `transactionManager` defaults to `transactionManager` (provided from the application context).
|
||||
Also, the `ItemProcessor` is optional, since the item could be
|
||||
directly passed from the reader to the writer.
|
||||
endif::backend-html5[]
|
||||
|
||||
@@ -354,16 +352,16 @@ value of 10 as it would be defined in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job sampleJob() {
|
||||
return this.jobBuilderFactory.get("sampleJob")
|
||||
public Job sampleJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("sampleJob", jobRepository)
|
||||
.start(step1())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(10)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.build();
|
||||
@@ -412,9 +410,9 @@ The following code fragment shows an example of a start limit configuration in J
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(10)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.startLimit(1)
|
||||
@@ -456,9 +454,9 @@ The following code fragment shows how to define a restartable job in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(10)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.allowStartIfComplete(true)
|
||||
@@ -506,8 +504,8 @@ restarted:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job footballJob() {
|
||||
return this.jobBuilderFactory.get("footballJob")
|
||||
public Job footballJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("footballJob", jobRepository)
|
||||
.start(playerLoad())
|
||||
.next(gameLoad())
|
||||
.next(playerSummarization())
|
||||
@@ -515,29 +513,29 @@ public Job footballJob() {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step playerLoad() {
|
||||
return this.stepBuilderFactory.get("playerLoad")
|
||||
.<String, String>chunk(10)
|
||||
public Step playerLoad(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("playerLoad", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(playerFileItemReader())
|
||||
.writer(playerWriter())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step gameLoad() {
|
||||
return this.stepBuilderFactory.get("gameLoad")
|
||||
public Step gameLoad(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("gameLoad", jobRepository)
|
||||
.allowStartIfComplete(true)
|
||||
.<String, String>chunk(10)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(gameFileItemReader())
|
||||
.writer(gameWriter())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step playerSummarization() {
|
||||
return this.stepBuilderFactory.get("playerSummarization")
|
||||
public Step playerSummarization(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("playerSummarization", jobRepository)
|
||||
.startLimit(2)
|
||||
.<String, String>chunk(10)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(playerSummarizationSource())
|
||||
.writer(summaryWriter())
|
||||
.build();
|
||||
@@ -635,9 +633,9 @@ The following Java example shows an example of using a skip limit:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(10)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(flatFileItemReader())
|
||||
.writer(itemWriter())
|
||||
.faultTolerant()
|
||||
@@ -687,9 +685,9 @@ The following Java example shows an example excluding a particular exception:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(10)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(flatFileItemReader())
|
||||
.writer(itemWriter())
|
||||
.faultTolerant()
|
||||
@@ -755,9 +753,9 @@ In Java, retry should be configured as follows:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(2)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(2, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.faultTolerant()
|
||||
@@ -805,9 +803,9 @@ In Java, you can control rollback as follows:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(2)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(2, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.faultTolerant()
|
||||
@@ -848,9 +846,9 @@ The following example shows how to create a reader that does not buffer items in
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(2)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(2, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.readerIsTransactionalQueue()
|
||||
@@ -892,14 +890,14 @@ attributes in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
||||
attribute.setPropagationBehavior(Propagation.REQUIRED.value());
|
||||
attribute.setIsolationLevel(Isolation.DEFAULT.value());
|
||||
attribute.setTimeout(30);
|
||||
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(2)
|
||||
return new StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(2, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(itemWriter())
|
||||
.transactionAttribute(attribute)
|
||||
@@ -957,9 +955,9 @@ The following example shows how to register a `stream` on a `step` in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(2)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(2, transactionManager)
|
||||
.reader(itemReader())
|
||||
.writer(compositeItemWriter())
|
||||
.stream(fileItemWriter1())
|
||||
@@ -1031,9 +1029,9 @@ The following example shows a listener applied at the chunk level in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.<String, String>chunk(10)
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return tnew StepBuilder("step1", jobRepository)
|
||||
.<String, String>chunk(10, transactionManager)
|
||||
.reader(reader())
|
||||
.writer(writer())
|
||||
.listener(chunkListener())
|
||||
@@ -1285,9 +1283,9 @@ building a `TaskletStep`. The following example shows a simple tasklet:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.tasklet(myTasklet())
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("step1", jobRepository)
|
||||
.tasklet(myTasklet(), transactionManager)
|
||||
.build();
|
||||
}
|
||||
----
|
||||
@@ -1311,9 +1309,9 @@ simple `tasklet`:
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public Step step1() {
|
||||
return this.stepBuilderFactory.get("step1")
|
||||
.tasklet(myTasklet())
|
||||
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("step1", jobRepository)
|
||||
.tasklet(myTasklet(), transactionManager)
|
||||
.build();
|
||||
}
|
||||
----
|
||||
@@ -1438,16 +1436,16 @@ The following example shows how to reference the `tasklet` from the `step` in Ja
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job taskletJob() {
|
||||
return this.jobBuilderFactory.get("taskletJob")
|
||||
public Job taskletJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("taskletJob", jobRepository)
|
||||
.start(deleteFilesInDir())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step deleteFilesInDir() {
|
||||
return this.stepBuilderFactory.get("deleteFilesInDir")
|
||||
.tasklet(fileDeletingTasklet())
|
||||
public Step deleteFilesInDir(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
|
||||
return new StepBuilder("deleteFilesInDir", jobRepository)
|
||||
.tasklet(fileDeletingTasklet(), transactionManager)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -1501,8 +1499,8 @@ The following example shows how to use the `next()` method in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(stepA())
|
||||
.next(stepB())
|
||||
.next(stepC())
|
||||
@@ -1573,8 +1571,8 @@ proceed to either of two different steps (`stepB` or `stepC`), depending on whet
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(stepA())
|
||||
.on("*").to(stepB())
|
||||
.from(stepA()).on("FAILED").to(stepC())
|
||||
@@ -1675,8 +1673,8 @@ The following example shows how to work with a different exit code in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(step1()).on("FAILED").end()
|
||||
.from(step1()).on("COMPLETED WITH SKIPS").to(errorPrint1())
|
||||
.from(step1()).on("*").to(step2())
|
||||
@@ -1741,8 +1739,8 @@ In the following Java example, after the `step` executes, the `Job` ends:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(step1())
|
||||
.build();
|
||||
}
|
||||
@@ -1811,8 +1809,8 @@ The following example shows the scenario in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(step1())
|
||||
.next(step2())
|
||||
.on("FAILED").end()
|
||||
@@ -1863,8 +1861,8 @@ The following example shows the scenario in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(step1())
|
||||
.next(step2()).on("FAILED").fail()
|
||||
.from(step2()).on("*").to(step3())
|
||||
@@ -1909,8 +1907,8 @@ The following example shows the scenario in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(step1()).on("COMPLETED").stopAndRestart(step2())
|
||||
.end()
|
||||
.build();
|
||||
@@ -1970,8 +1968,8 @@ directly to the `next` call when using Java configuration:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(step1())
|
||||
.next(decider()).on("FAILED").to(step2())
|
||||
.from(decider()).on("COMPLETED").to(step3())
|
||||
@@ -2076,8 +2074,8 @@ elsewhere:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(flow1())
|
||||
.next(step3())
|
||||
.end()
|
||||
@@ -2130,15 +2128,15 @@ The following example shows an example of a `JobStep` in Java:
|
||||
[source, java, role="javaContent"]
|
||||
----
|
||||
@Bean
|
||||
public Job jobStepJob() {
|
||||
return this.jobBuilderFactory.get("jobStepJob")
|
||||
public Job jobStepJob(JobRepository jobRepository) {
|
||||
return new JobBuilder("jobStepJob", jobRepository)
|
||||
.start(jobStepJobStep1(null))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step jobStepJobStep1(JobLauncher jobLauncher) {
|
||||
return this.stepBuilderFactory.get("jobStepJobStep1")
|
||||
public Step jobStepJobStep1(JobLauncher jobLauncher, JobRepository jobRepository) {
|
||||
return new StepBuilder("jobStepJobStep1", jobRepository)
|
||||
.job(job())
|
||||
.launcher(jobLauncher)
|
||||
.parametersExtractor(jobParametersExtractor())
|
||||
@@ -2146,8 +2144,8 @@ public Step jobStepJobStep1(JobLauncher jobLauncher) {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Job job() {
|
||||
return this.jobBuilderFactory.get("job")
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
.start(step1())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -47,20 +47,22 @@ This release also marks the migration to:
|
||||
|
||||
Spring Batch 5 includes the following infrastructure configuration updates:
|
||||
|
||||
* <<datasource-requirement-updates>>
|
||||
* <<datasource-transaction-manager-requirement-updates>>
|
||||
* <<transaction-manager-bean-exposure>>
|
||||
* <<default-transaction-manager-type>>
|
||||
* <<new-attributes-enable-batch-processing>>
|
||||
* <<new-configuration-class>>
|
||||
* <<transaction-support-in-job-explorer-and-job-operator>>
|
||||
|
||||
[[datasource-requirement-updates]]
|
||||
==== DataSource Requirement Updates
|
||||
[[datasource-transaction-manager-requirement-updates]]
|
||||
==== Data Source and Transaction manager Requirement Updates
|
||||
|
||||
Historically, Spring Batch provided a map-based job repository and job explorer implementations to work with
|
||||
an in-memory job repository. These implementations were deprecated in version 4 and completely removed in version 5.
|
||||
The recommended replacement is to use the JDBC-based implementations with an embedded database, such as H2, HSQL, and others.
|
||||
|
||||
In this release, the `@EnableBatchProcessing` annotation configures a JDBC-based `JobRepository`, which requires a
|
||||
`DataSource` bean in the application context. The `DataSource` bean could refer to an embedded database to work with
|
||||
an in-memory job repository.
|
||||
`DataSource` and `PlatformTransactionManager` beans to be defined in the application context. The `DataSource` bean
|
||||
could refer to an embedded database to work with an in-memory job repository.
|
||||
|
||||
[[transaction-manager-bean-exposure]]
|
||||
==== Transaction Manager Bean Exposure
|
||||
@@ -70,13 +72,87 @@ context. While this was convenient in many cases, the unconditional exposure of
|
||||
interfere with a user-defined transaction manager. In this release, `@EnableBatchProcessing` no longer exposes a
|
||||
transaction manager bean in the application context.
|
||||
|
||||
[[default-transaction-manager-type]]
|
||||
==== Default Transaction Manager Type
|
||||
[[new-attributes-enable-batch-processing]]
|
||||
==== New annotation attributes in EnableBatchProcessing
|
||||
|
||||
When no transaction manager is specified, `@EnableBatchProcessing` used (up to version 4.3) to register a default
|
||||
transaction manager of type `org.springframework.jdbc.datasource.DataSourceTransactionManager` in the proxy around
|
||||
`JobRepository` when a `DataSource` bean is defined in the application context. In this release, the type of the
|
||||
default transaction manager has changed to `org.springframework.jdbc.support.JdbcTransactionManager`.
|
||||
In this release, the `@EnableBatchProcessing` annotation provides new attributes to specify which
|
||||
components and parameters should be used to configure the Batch infrastructure beans. For example,
|
||||
it is now possible to specify which data source and transaction manager Spring Batch should configure
|
||||
in the job repository as follows:
|
||||
|
||||
```
|
||||
@Configuration
|
||||
@EnableBatchProcessing(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager")
|
||||
public class MyJobConfiguration {
|
||||
|
||||
@Bean
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("myJob", jobRepository)
|
||||
//define job flow as needed
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
In this example, `batchDataSource` and `batchTransactionManager` refer to beans in the application context,
|
||||
and which will be used to configure the job repository and job explorer. There is no need to define a
|
||||
custom `BatchConfiguer` anymore, which was removed in this release.
|
||||
|
||||
[[new-configuration-class]]
|
||||
==== New configuration class for infrastructure beans
|
||||
|
||||
In this release, a new configuration class named `DefaultBatchConfiguration` can be used as an alternative to
|
||||
using `@EnableBatchProcessing` for the configuration of infrastrucutre beans. This class provides infrastructure
|
||||
beans with default configuration which can be customized as needed. The following snippet shows a typical usage
|
||||
of this class:
|
||||
|
||||
```
|
||||
@Configuration
|
||||
class MyJobConfiguration extends DefaultBatchConfiguration {
|
||||
|
||||
@Bean
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("myJob", jobRepository)
|
||||
//define job flow as needed
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
In this example, the `JobRepository` bean injected in the `Job` bean definition is defined in the `DefaultBatchConfiguration`
|
||||
class. Custom parameters can be specified by overriding the corresponding getter. For example, the following example shows
|
||||
how to override the default character encoding used in the job repository and job explorer:
|
||||
|
||||
```
|
||||
@Configuration
|
||||
class MyJobConfiguration extends DefaultBatchConfiguration {
|
||||
|
||||
@Bean
|
||||
public Job job(JobRepository jobRepository) {
|
||||
return new JobBuilder("job", jobRepository)
|
||||
// define job flow as needed
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Charset getCharset() {
|
||||
return StandardCharsets.ISO_8859_1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[[transaction-support-in-job-explorer-and-job-operator]]
|
||||
=== Transaction support in JobExplorer and JobOperator
|
||||
|
||||
This release introduces transaction support in the `JobExplorer` created through
|
||||
the `JobExplorerFactoryBean`. It is now possible to specify which transaction manager
|
||||
to use to drive the ready-only transactions when querying the Batch meta-data as well as
|
||||
customizing the transaction attributes.
|
||||
|
||||
The same transaction support was added to the `JobOperator` through a new factory bean
|
||||
named `JobOperatorFactoryBean`.
|
||||
|
||||
[[batch-testing-configuration-updates]]
|
||||
=== Batch Testing Configuration Updates
|
||||
|
||||
Reference in New Issue
Block a user