Users can specify different datasources for the jdbc-item reader and or jdbc-item writer

Users can specify a unique data source for the JdbcCursorItemReader and or writer instead of using the default datasource.
If a jdbc-item-reader or jdbc-item-writer data source is not specified the default will be used by the reader or writer.

Updated docs

Updated readme docs
This commit is contained in:
Glenn Renfro
2022-06-15 07:50:14 -04:00
parent 0e56642c53
commit 6029b47592
8 changed files with 343 additions and 25 deletions

View File

@@ -287,6 +287,39 @@ can also use the following properties to configure a `JdbcCursorItemReader`:
| SQL query from which to read.
|===
You can also specify JDBC DataSource specifically for the reader by using the following properties:
.`JdbcCursorItemReader` Properties
|===
| Property | Type | Default Value | Description
| `spring.batch.job.jdbccursoritemreader.datasource.enable`
| `boolean`
| `false`
| Determines whether `JdbcCursorItemReader` `DataSource` should be enabled.
| `jdbccursoritemreader.datasource.url`
| `String`
| `null`
| JDBC URL of the database.
| `jdbccursoritemreader.datasource.username`
| `String`
| `null`
| Login username of the database.
| `jdbccursoritemreader.datasource.password`
| `String`
| `null`
| Login password of the database.
| `jdbccursoritemreader.datasource.driver-class-name`
| `String`
| `null`
| Fully qualified name of the JDBC driver.
|===
NOTE: The default `DataSource` will be used by the `JDBCCursorItemReader` if the `jdbccursoritemreader_datasource` is not specified.
See the https://docs.spring.io/spring-batch/docs/4.3.x/api/org/springframework/batch/item/database/JdbcCursorItemReader.html[`JdbcCursorItemReader` documentation].
[[kafkaItemReader]]
@@ -505,6 +538,39 @@ configuration options by setting the following properties:
| Whether to verify that every insert results in the update of at least one record.
|===
You can also specify JDBC DataSource specifically for the writer by using the following properties:
.`JdbcBatchItemWriter` Properties
|===
| Property | Type | Default Value | Description
| `spring.batch.job.jdbcbatchitemwriter.datasource.enable`
| `boolean`
| `false`
| Determines whether `JdbcCursorItemReader` `DataSource` should be enabled.
| `jdbcbatchitemwriter.datasource.url`
| `String`
| `null`
| JDBC URL of the database.
| `jdbcbatchitemwriter.datasource.username`
| `String`
| `null`
| Login username of the database.
| `jdbcbatchitemwriter.datasource.password`
| `String`
| `null`
| Login password of the database.
| `jdbcbatchitemreader.datasource.driver-class-name`
| `String`
| `null`
| Fully qualified name of the JDBC driver.
|===
NOTE: The default `DataSource` will be used by the `JdbcBatchItemWriter` if the `jdbcbatchitemwriter_datasource` is not specified.
See the https://docs.spring.io/spring-batch/docs/4.3.x/api/org/springframework/batch/item/database/JdbcBatchItemWriter.html[`JdbcBatchItemWriter` documentation].
[[kafkaitemwriter]]

View File

@@ -17,6 +17,10 @@
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-task-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2022-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.task.batch.autoconfigure.jdbc;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.task.configuration.DefaultTaskConfigurer;
import org.springframework.cloud.task.configuration.TaskConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
/**
* Establishes the default {@link DataSource} for the Task when creating a {@link DataSource}
* for {@link org.springframework.batch.item.database.JdbcCursorItemReader}
* or {@link org.springframework.batch.item.database.JdbcBatchItemWriter}.
*
* @author Glenn Renfro
* @since 3.0
*/
class JDBCSingleStepDataSourceAutoConfiguration {
@ConditionalOnMissingBean
@Bean
public TaskConfigurer myTaskConfigurer(DataSource dataSource) {
return new DefaultTaskConfigurer(dataSource);
}
@ConditionalOnProperty(prefix = "spring.batch.job.jdbcsinglestep.datasource", name = "enable", havingValue = "true", matchIfMissing = true)
@ConditionalOnMissingBean(name = "springDataSourceProperties")
@Bean(name = "springDataSourceProperties")
@ConfigurationProperties("spring.datasource")
@Primary
public DataSourceProperties springDataSourceProperties() {
return new DataSourceProperties();
}
@ConditionalOnProperty(prefix = "spring.batch.job.jdbcsinglestep.datasource", name = "enable", havingValue = "true", matchIfMissing = true)
@Bean(name = "springDataSource")
@Primary
public DataSource dataSource(@Qualifier("springDataSourceProperties")DataSourceProperties springDataSourceProperties) {
DataSource dataSource = springDataSourceProperties.initializeDataSourceBuilder().build();
return dataSource;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2020 the original author or authors.
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,18 +20,26 @@ import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.database.ItemPreparedStatementSetter;
import org.springframework.batch.item.database.ItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Autconfiguration for a {@code JdbcBatchItemWriter}.
@@ -43,14 +51,21 @@ import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(JdbcBatchItemWriterProperties.class)
@AutoConfigureAfter(BatchAutoConfiguration.class)
@Import(JDBCSingleStepDataSourceAutoConfiguration.class)
public class JdbcBatchItemWriterAutoConfiguration {
private static final Log logger = LogFactory
.getLog(JdbcBatchItemWriterAutoConfiguration.class);
@Autowired(required = false)
private ItemPreparedStatementSetter itemPreparedStatementSetter;
@Autowired(required = false)
private ItemSqlParameterSourceProvider itemSqlParameterSourceProvider;
@Autowired
ApplicationContext applicationContext;
private JdbcBatchItemWriterProperties properties;
private DataSource dataSource;
@@ -65,9 +80,16 @@ public class JdbcBatchItemWriterAutoConfiguration {
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.batch.job.jdbcbatchitemwriter", name = "name")
public JdbcBatchItemWriter<Map<String, Object>> itemWriter() {
DataSource writerDataSource = this.dataSource;
try {
writerDataSource = this.applicationContext.getBean("jdbcBatchItemWriterSpringDataSource", DataSource.class);
}
catch (Exception ex) {
logger.info("Using Default Data Source for the JdbcBatchItemWriter");
}
JdbcBatchItemWriterBuilder<Map<String, Object>> jdbcBatchItemWriterBuilder = new JdbcBatchItemWriterBuilder<Map<String, Object>>()
.dataSource(this.dataSource).sql(this.properties.getSql());
.dataSource(writerDataSource).sql(this.properties.getSql());
if (this.itemPreparedStatementSetter != null) {
jdbcBatchItemWriterBuilder
.itemPreparedStatementSetter(this.itemPreparedStatementSetter);
@@ -83,4 +105,17 @@ public class JdbcBatchItemWriterAutoConfiguration {
return jdbcBatchItemWriterBuilder.build();
}
@ConditionalOnProperty(prefix = "spring.batch.job.jdbcbatchitemwriter.datasource", name = "enable", havingValue = "true")
@Bean(name = "jdbcBatchItemWriterDataSourceProperties")
@ConfigurationProperties("jdbcbatchitemwriter.datasource")
public DataSourceProperties jdbcBatchItemWriterDataSourceProperties() {
return new DataSourceProperties();
}
@ConditionalOnProperty(prefix = "spring.batch.job.jdbcbatchitemwriter.datasource", name = "enable", havingValue = "true")
@Bean(name = "jdbcBatchItemWriterSpringDataSource")
public DataSource writerDataSource(@Qualifier("jdbcBatchItemWriterDataSourceProperties") DataSourceProperties writerDataSourceProperties) {
DataSource result = writerDataSourceProperties.initializeDataSourceBuilder().build();
return result;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,16 +23,24 @@ import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.database.JdbcCursorItemReader;
import org.springframework.batch.item.database.builder.JdbcCursorItemReaderBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowMapper;
@@ -45,8 +53,15 @@ import org.springframework.jdbc.core.RowMapper;
@EnableConfigurationProperties(JdbcCursorItemReaderProperties.class)
@AutoConfigureAfter(BatchAutoConfiguration.class)
@ConditionalOnProperty(prefix = "spring.batch.job.jdbccursoritemreader", name = "name")
@Import(JDBCSingleStepDataSourceAutoConfiguration.class)
public class JdbcCursorItemReaderAutoConfiguration {
private static final Log logger = LogFactory
.getLog(JdbcCursorItemReaderAutoConfiguration.class);
@Autowired
ApplicationContext applicationContext;
private final JdbcCursorItemReaderProperties properties;
private final DataSource dataSource;
@@ -61,10 +76,18 @@ public class JdbcCursorItemReaderAutoConfiguration {
@ConditionalOnMissingBean
public JdbcCursorItemReader<Map<String, Object>> itemReader(@Autowired(required = false) RowMapper<Map<String, Object>> rowMapper,
@Autowired(required = false) PreparedStatementSetter preparedStatementSetter) {
DataSource readerDataSource = this.dataSource;
try {
readerDataSource = this.applicationContext.getBean("jdbcCursorItemReaderSpringDataSource", DataSource.class);
}
catch (Exception e) {
logger.info("Using Default Data Source for the JdbcCursorItemReader");
}
return new JdbcCursorItemReaderBuilder<Map<String, Object>>()
.name(this.properties.getName())
.currentItemCount(this.properties.getCurrentItemCount())
.dataSource(this.dataSource)
.dataSource(readerDataSource)
.driverSupportsAbsolute(this.properties.isDriverSupportsAbsolute())
.fetchSize(this.properties.getFetchSize())
.ignoreWarnings(this.properties.isIgnoreWarnings())
@@ -86,6 +109,20 @@ public class JdbcCursorItemReaderAutoConfiguration {
return new MapRowMapper();
}
@ConditionalOnProperty(prefix = "spring.batch.job.jdbccursoritemreader.datasource", name = "enable", havingValue = "true")
@Bean(name = "jdbcCursorItemReaderDataSourceProperties")
@ConfigurationProperties("jdbccursoritemreader.datasource")
public DataSourceProperties jdbcCursorItemReaderDataSourceProperties() {
return new DataSourceProperties();
}
@ConditionalOnProperty(prefix = "spring.batch.job.jdbccursoritemreader.datasource", name = "enable", havingValue = "true")
@Bean(name = "jdbcCursorItemReaderSpringDataSource")
public DataSource readerDataSource(@Qualifier("jdbcCursorItemReaderDataSourceProperties")DataSourceProperties readerDataSourceProperties) {
DataSource result = readerDataSourceProperties.initializeDataSourceBuilder().build();
return result;
}
public static class MapRowMapper implements RowMapper<Map<String, Object>> {
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2020 the original author or authors.
* Copyright 2020-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ import org.springframework.batch.item.database.ItemPreparedStatementSetter;
import org.springframework.batch.item.database.ItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
@@ -59,6 +60,7 @@ import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class JdbcBatchItemWriterAutoConfigurationTests {
@@ -106,10 +108,37 @@ public class JdbcBatchItemWriterAutoConfigurationTests {
AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
BatchAutoConfiguration.class,
SingleStepJobAutoConfiguration.class,
JdbcBatchItemWriterAutoConfiguration.class));
JdbcBatchItemWriterAutoConfiguration.class))
.withPropertyValues("spring.batch.job.jdbcsinglestep.datasource.enable=false");
applicationContextRunner = updatePropertiesForTest(applicationContextRunner);
runTest(applicationContextRunner);
runTest(applicationContextRunner, false);
}
@Test
public void baseTestWithWriterDataSource() {
ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner()
.withUserConfiguration(
TaskLauncherConfiguration.class,
JdbcBatchItemWriterAutoConfigurationTests.DelimitedJobConfiguration.class
)
.withConfiguration(
AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
BatchAutoConfiguration.class,
SingleStepJobAutoConfiguration.class,
JdbcBatchItemWriterAutoConfiguration.class))
.withPropertyValues("spring.batch.job.jdbcbatchitemwriter.datasource.enable=true",
"spring.batch.job.jdbcsinglestep.datasource.enable=false",
"spring.batch.job.jobName=job",
"spring.batch.job.stepName=step1", "spring.batch.job.chunkSize=5",
"spring.batch.job.jdbcbatchitemwriter.name=fooWriter",
"spring.batch.job.jdbcbatchitemwriter.sql=INSERT INTO item (item_name) VALUES (:item_name)",
"spring.batch.jdbc.initialize-schema=always",
"jdbcbatchitemwriter.datasource.url=" + DATASOURCE_URL,
"jdbcbatchitemwriter.datasource.username=" + DATASOURCE_USER_NAME,
"jdbcbatchitemwriter.datasource.password=" + DATASOURCE_USER_PASSWORD,
"jdbcbatchitemwriter.datasource.driverClassName=" + DATASOURCE_DRIVER_CLASS_NAME);
runTest(applicationContextRunner, true);
}
@Test
@@ -123,10 +152,11 @@ public class JdbcBatchItemWriterAutoConfigurationTests {
AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
BatchAutoConfiguration.class,
SingleStepJobAutoConfiguration.class,
JdbcBatchItemWriterAutoConfiguration.class));
JdbcBatchItemWriterAutoConfiguration.class))
.withPropertyValues("spring.batch.job.jdbcsinglestep.datasource.enable=false");
applicationContextRunner = updatePropertiesForTest(applicationContextRunner);
runTest(applicationContextRunner);
runTest(applicationContextRunner, false);
}
@Test
@@ -140,9 +170,10 @@ public class JdbcBatchItemWriterAutoConfigurationTests {
AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
BatchAutoConfiguration.class,
SingleStepJobAutoConfiguration.class,
JdbcBatchItemWriterAutoConfiguration.class));
JdbcBatchItemWriterAutoConfiguration.class))
.withPropertyValues("spring.batch.job.jdbcsinglestep.datasource.enable=false");
applicationContextRunner = updatePropertiesForTest(applicationContextRunner);
runTest(applicationContextRunner);
runTest(applicationContextRunner, false);
}
private ApplicationContextRunner updatePropertiesForTest(
@@ -154,8 +185,14 @@ public class JdbcBatchItemWriterAutoConfigurationTests {
"spring.batch.jdbc.initialize-schema=always");
}
private void validateResultAndBean(ApplicationContext context) {
DataSource dataSource = context.getBean(DataSource.class);
private void validateResultAndBean(ApplicationContext context, boolean isWriterDataSourcePresent) {
DataSource dataSource;
try {
dataSource = context.getBean(DataSource.class);
}
catch (NoSuchBeanDefinitionException nde) {
dataSource = context.getBean("jdbcBatchItemWriterSpringDataSource", DataSource.class);
}
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<Map<String, Object>> result = jdbcTemplate
.queryForList("SELECT item_name FROM item ORDER BY item_name");
@@ -172,9 +209,17 @@ public class JdbcBatchItemWriterAutoConfigurationTests {
.isEqualTo(1);
assertThat((Boolean) ReflectionTestUtils.getField(writer, "usingNamedParameters"))
.isTrue();
if (!isWriterDataSourcePresent) {
assertThatThrownBy(() -> context.getBean("jdbcBatchItemWriterSpringDataSource"))
.isInstanceOf(NoSuchBeanDefinitionException.class)
.hasMessageContaining("No bean named 'jdbcBatchItemWriterSpringDataSource' available");
}
else {
assertThat(context.getBean("jdbcBatchItemWriterSpringDataSource")).isNotNull();
}
}
private void runTest(ApplicationContextRunner applicationContextRunner) {
private void runTest(ApplicationContextRunner applicationContextRunner, boolean isWriterDataSourcePresent) {
applicationContextRunner.run((context) -> {
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
@@ -188,7 +233,7 @@ public class JdbcBatchItemWriterAutoConfigurationTests {
Thread.sleep(1000);
}
validateResultAndBean(context);
validateResultAndBean(context, isWriterDataSourcePresent);
});
}

View File

@@ -36,7 +36,9 @@ import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.item.database.JdbcCursorItemReader;
import org.springframework.batch.item.support.ListItemWriter;
import org.springframework.batch.item.util.ExecutionContextUserSupport;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -56,6 +58,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* @author Michael Minella
* @author Glenn Renfro
*/
public class JdbcCursorItemReaderAutoConfigurationTests {
@@ -90,18 +93,13 @@ public class JdbcCursorItemReaderAutoConfigurationTests {
@Test
public void testIntegration() {
ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner()
.withUserConfiguration(TaskLauncherConfiguration.class, BaseConfiguration.class)
.withConfiguration(
AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
BatchAutoConfiguration.class,
SingleStepJobAutoConfiguration.class,
JdbcCursorItemReaderAutoConfiguration.class))
ApplicationContextRunner applicationContextRunner = applicationContextRunner()
.withPropertyValues("spring.batch.job.jobName=integrationJob",
"spring.batch.job.stepName=step1", "spring.batch.job.chunkSize=5",
"spring.batch.job.jdbccursoritemreader.name=fooReader",
"spring.batch.job.jdbccursoritemreader.sql=select item_name from item",
"spring.batch.jdbc.initialize-schema=always");
"spring.batch.jdbc.initialize-schema=always",
"spring.batch.job.jdbcsinglestep.datasource.enable=false");
applicationContextRunner.run((context) -> {
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
@@ -123,6 +121,58 @@ public class JdbcCursorItemReaderAutoConfigurationTests {
assertThat(items.get(0).get("ITEM_NAME")).isEqualTo("foo");
assertThat(items.get(1).get("ITEM_NAME")).isEqualTo("bar");
assertThat(items.get(2).get("ITEM_NAME")).isEqualTo("baz");
assertThatThrownBy(() -> context.getBean("readerSpringDataSource"))
.isInstanceOf(NoSuchBeanDefinitionException.class)
.hasMessageContaining("No bean named 'readerSpringDataSource' available");
});
}
private ApplicationContextRunner applicationContextRunner() {
return new ApplicationContextRunner()
.withUserConfiguration(TaskLauncherConfiguration.class, BaseConfiguration.class)
.withConfiguration(
AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
BatchAutoConfiguration.class,
SingleStepJobAutoConfiguration.class,
JdbcCursorItemReaderAutoConfiguration.class));
}
@Test
public void testIntegrationReaderDataSourceEnabled() {
ApplicationContextRunner applicationContextRunner = applicationContextRunner()
.withPropertyValues("spring.batch.job.jobName=integrationReaderJob",
"spring.batch.job.stepName=step1", "spring.batch.job.chunkSize=5",
"spring.batch.job.jdbccursoritemreader.name=fooReader",
"spring.batch.job.jdbccursoritemreader.sql=select item_name from item",
"spring.batch.jdbc.initialize-schema=always",
"spring.batch.job.jdbcsinglestep.datasource.enable=false",
"spring.batch.job.jdbccursoritemreader.datasource.enable=true",
"jdbccursoritemreader.datasource.url=" + DATASOURCE_URL,
"jdbccursoritemreader.datasource.username=" + DATASOURCE_USER_NAME,
"jdbccursoritemreader.datasource.password=" + DATASOURCE_USER_PASSWORD,
"jdbccursoritemreader.datasource.driverClassName=" + DATASOURCE_DRIVER_CLASS_NAME);
applicationContextRunner.run((context) -> {
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
JobExplorer jobExplorer = context.getBean(JobExplorer.class);
while (jobExplorer.getJobExecution(jobExecution.getJobId()).isRunning()) {
Thread.sleep(1000);
}
List<Map<String, Object>> items = context.getBean(ListItemWriter.class)
.getWrittenItems();
assertThat(items.size()).isEqualTo(3);
assertThat(items.get(0).get("ITEM_NAME")).isEqualTo("foo");
assertThat(items.get(1).get("ITEM_NAME")).isEqualTo("bar");
assertThat(items.get(2).get("ITEM_NAME")).isEqualTo("baz");
assertThat(context.getBean("jdbcCursorItemReaderSpringDataSource")).isNotNull();
});
}
@@ -139,7 +189,8 @@ public class JdbcCursorItemReaderAutoConfigurationTests {
"spring.batch.job.stepName=step1", "spring.batch.job.chunkSize=5",
"spring.batch.job.jdbccursoritemreader.name=fooReader",
"spring.batch.job.jdbccursoritemreader.sql=select * from item",
"spring.batch.jdbc.initialize-schema=always");
"spring.batch.jdbc.initialize-schema=always",
"spring.batch.job.jdbcsinglestep.datasource.enable=false");
applicationContextRunner.run((context) -> {
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
@@ -281,6 +332,7 @@ public class JdbcCursorItemReaderAutoConfigurationTests {
});
}
@AutoConfigureBefore({JdbcCursorItemReaderAutoConfiguration.class, JDBCSingleStepDataSourceAutoConfiguration.class})
@Configuration
public static class TaskLauncherConfiguration {

View File

@@ -58,7 +58,7 @@ CREATE TABLE IF NOT EXISTS item
```
=== JdbcCursorItemReader with a JdbcItemWriter batch job
In this example the batch job will read from the `item_sample` table in your data store and write the result to the `item` table in your data store.
In this example the batch job will read from the `item_sample` table in your data store (as specified in the default `DataSource` properties) and write the result to the `item` table in your data store (as specified in the default `DataSource` properties).
```
java -Dspring.profiles.active=jdbcreader,jdbcwriter -jar target/single-step-batch-job-2.3.0-SNAPSHOT.jar
```
@@ -82,6 +82,22 @@ INSERT INTO item_sample (item_name) VALUES ('qux');
INSERT INTO item_sample (item_name) VALUES ('Job');
```
You may also wish to read from and write to data sources different from the default `DataSource`. This can be done specifying datasources for the reader and writer as follows:
```
# Jdbc Cursor Item Reader Data Source
export jdbccursoritemreader_datasource_url=<your reader database>
export jdbccursoritemreader_datasource_username=<your user>
export jdbccursoritemreader_datasource_password=<your password>
export jdbccursoritemreader_datasource_driverClassName=<your driver classname>
export spring_batch_job_jdbccursoritemreader_datasource_enable=true
# Jdbc Batch Item Writer Data Source
export jdbcbatchitemwriter_datasource_url=<your writer database>
export jdbcbatchitemwriter_datasource_username=<your user>
export jdbcbatchitemwriter_datasource_password=<your password>
export jdbcbatchitemwriter_datasource_driverClassName=<your driver classname>
export spring_batch_job_jdbcbatchitemwriter_datasource_enable=true
```
=== JdbcCursorItemReader with FlatfileItemWriter batch job
In this example the batch job will read from the `item_sample` table in your data store and write the result to the `result.txt` file to the root directory of the project.
```