diff --git a/.gitignore b/.gitignore
index 5badee7c..de421b99 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@ out
spring-shell.log
target/
test-output
+result.txt
# Eclipse artifacts, including WTP generated manifests
.classpath
diff --git a/spring-cloud-task-samples/pom.xml b/spring-cloud-task-samples/pom.xml
index 54e82601..598355e9 100644
--- a/spring-cloud-task-samples/pom.xml
+++ b/spring-cloud-task-samples/pom.xml
@@ -29,6 +29,7 @@
batch-events
jpa-sample
multiple-datasources
+ single-step-batch-job
diff --git a/spring-cloud-task-samples/single-step-batch-job/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-task-samples/single-step-batch-job/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 00000000..5fd4d502
Binary files /dev/null and b/spring-cloud-task-samples/single-step-batch-job/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/spring-cloud-task-samples/single-step-batch-job/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-task-samples/single-step-batch-job/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000..a3f9f187
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
diff --git a/spring-cloud-task-samples/single-step-batch-job/README.adoc b/spring-cloud-task-samples/single-step-batch-job/README.adoc
new file mode 100644
index 00000000..166580be
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/README.adoc
@@ -0,0 +1,100 @@
+= Timestamp Task
+
+This is a Spring Cloud Task application that autoconfigures a single step Spring Batch job based on the profiles that are active.
+
+The profiles that are available are:
+
+* `ffreader` - Activates a FlatFileItemReader that reads from the `test.txt` file provided.
+* `ffwriter` - Activates a FlatFileItemWriter that writes to the `result.txt` file.
+* `jdbcreader` - Activates a JdbcCursorItemReader that reads from the `item_sample` table.
+* `jdbcwriter` - Activates a JdbcItemReader that writes to the `item` table.
+
+== Requirements:
+
+* Java 8 or Above
+
+== Classes:
+
+* SingleStepBatchJobApplication - the Spring Boot Main Application
+
+== Build:
+
+[source,shell,indent=2]
+----
+$ mvn clean package
+----
+
+== Run:
+
+[source,shell,indent=2]
+----
+$ java -jar target/single-step-batch-job-2.3.0-SNAPSHOT.jar --spring.config.name=
+----
+
+== Examples
+
+=== FlatFileItemReader with a FlatFileItemWriter batch job
+In this example the batch job will read from the test.txt file from the resources directory and write a `result.txt` file to the root directory of the project.
+```
+java -Dspring.profiles.active=ffreader,ffwriter -jar target/single-step-batch-job-2.3.0-SNAPSHOT.jar
+```
+
+=== FlatFileItemReader with a JdbcItemWriter batch job
+In this example the batch job will read from the test.txt file from the resources directory and write the result to the `item` table in your data store.
+```
+java -Dspring.profiles.active=ffreader,jdbcwriter -jar target/single-step-batch-job-2.3.0-SNAPSHOT.jar
+```
+
+Before running create the following table:
+```
+CREATE TABLE IF NOT EXISTS item
+(
+ item_name varchar(55)
+);
+```
+
+=== 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.
+```
+java -Dspring.profiles.active=jdbcreader,jdbcwriter -jar target/single-step-batch-job-2.3.0-SNAPSHOT.jar
+```
+
+Before running create the following tables:
+```
+CREATE TABLE IF NOT EXISTS item
+(
+ item_name varchar(55)
+);
+CREATE TABLE IF NOT EXISTS item_sample
+(
+ ITEM_NAME varchar(55)
+);
+
+INSERT INTO item_sample (item_name) VALUES ('foo');
+INSERT INTO item_sample (item_name) VALUES ('bar');
+INSERT INTO item_sample (item_name) VALUES ('baz');
+INSERT INTO item_sample (item_name) VALUES ('boo');
+INSERT INTO item_sample (item_name) VALUES ('qux');
+INSERT INTO item_sample (item_name) VALUES ('Job');
+```
+
+=== 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.
+```
+java -Dspring.profiles.active=jdbcreader,ffwriter -jar target/single-step-batch-job-2.3.0-SNAPSHOT.jar
+```
+
+Before running create the following table:
+```
+CREATE TABLE IF NOT EXISTS item_sample
+(
+ ITEM_NAME varchar(55)
+);
+
+INSERT INTO item_sample (item_name) VALUES ('foo');
+INSERT INTO item_sample (item_name) VALUES ('bar');
+INSERT INTO item_sample (item_name) VALUES ('baz');
+INSERT INTO item_sample (item_name) VALUES ('boo');
+INSERT INTO item_sample (item_name) VALUES ('qux');
+INSERT INTO item_sample (item_name) VALUES ('Job');
+```
diff --git a/spring-cloud-task-samples/single-step-batch-job/mvnw b/spring-cloud-task-samples/single-step-batch-job/mvnw
new file mode 100755
index 00000000..02217b1e
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/mvnw
@@ -0,0 +1,233 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ #
+ # Look for the Apple JDKs first to preserve the existing behaviour, and then look
+ # for the new JDKs provided by Oracle.
+ #
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
+ #
+ # Oracle JDKs
+ #
+ export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=`/usr/libexec/java_home`
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ local basedir=$(pwd)
+ local wdir=$(pwd)
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ wdir=$(cd "$wdir/.."; pwd)
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} "$@"
diff --git a/spring-cloud-task-samples/single-step-batch-job/pom.xml b/spring-cloud-task-samples/single-step-batch-job/pom.xml
new file mode 100644
index 00000000..a14eedaa
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/pom.xml
@@ -0,0 +1,174 @@
+
+
+
+ 4.0.0
+
+ io.spring.cloud
+ single-step-batch-job
+ jar
+ Single Step Batch Job Task
+ 2.3.0-SNAPSHOT
+ Spring Cloud Single Step Batch Job Task
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.4.0-SNAPSHOT
+
+
+
+
+ true
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-task-dependencies
+ 2.3.0-SNAPSHOT
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-task-core
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ com.h2database
+ h2
+
+
+ org.mariadb.jdbc
+ mariadb-java-client
+
+
+ org.springframework.boot
+ spring-boot-starter-batch
+
+
+ org.springframework.cloud
+ spring-cloud-starter-single-step-batch-job
+ 2.3.0-SNAPSHOT
+
+
+ org.springframework.batch
+ spring-batch-test
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/libs-snapshot-local
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/libs-milestone-local
+
+ false
+
+
+
+ spring-releases
+ Spring Releases
+ https://repo.spring.io/release
+
+ false
+
+
+
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/libs-snapshot-local
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/libs-milestone-local
+
+ false
+
+
+
+ spring-releases
+ Spring Releases
+ https://repo.spring.io/release
+
+ false
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.0.1
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
diff --git a/spring-cloud-task-samples/single-step-batch-job/src/main/java/io/spring/SingleStepBatchJobApplication.java b/spring-cloud-task-samples/single-step-batch-job/src/main/java/io/spring/SingleStepBatchJobApplication.java
new file mode 100644
index 00000000..6174653f
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/src/main/java/io/spring/SingleStepBatchJobApplication.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020-2020 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 io.spring;
+
+import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.task.configuration.EnableTask;
+
+@EnableTask
+@SpringBootApplication
+@EnableBatchProcessing
+public class SingleStepBatchJobApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SingleStepBatchJobApplication.class, args);
+ }
+}
diff --git a/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-ffreader.properties b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-ffreader.properties
new file mode 100644
index 00000000..1c776305
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-ffreader.properties
@@ -0,0 +1,9 @@
+spring.batch.job.flatfilereader.savestate=true
+spring.batch.job.flatfilereader.name=fixedWidthConfiguration
+spring.batch.job.flatfilereader.comments=#,$
+spring.batch.job.flatfilereader.resource=/test.txt
+spring.batch.job.flatfilereader.strict=true
+spring.batch.job.flatfilereader.fixedLength=true
+spring.batch.job.flatfilereader.ranges=1-3
+spring.batch.job.flatfilereader.names=ITEM_NAME
+spring.batch.job.flatfilereader.parsingStrict=false
diff --git a/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-ffwriter.properties b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-ffwriter.properties
new file mode 100644
index 00000000..bd2f7ef9
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-ffwriter.properties
@@ -0,0 +1,11 @@
+spring.batch.job.flatfilewriter.name=fooWriter
+spring.batch.job.flatfilewriter.resource=file:result.txt
+spring.batch.job.flatfilewriter.encoding=UTF-16
+spring.batch.job.flatfilewriter.saveState=false
+spring.batch.job.flatfilewriter.shouldDeleteIfEmpty=true
+spring.batch.job.flatfilewriter.delimited=true
+spring.batch.job.flatfilewriter.names=ITEM_NAME
+spring.batch.job.flatfilewriter.append=true
+spring.batch.job.flatfilewriter.forceSync=true
+spring.batch.job.flatfilewriter.shouldDeleteIfExists=false
+spring.batch.job.flatfilewriter.transactional=false
diff --git a/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-jdbcreader.properties b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-jdbcreader.properties
new file mode 100644
index 00000000..c94a43c0
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-jdbcreader.properties
@@ -0,0 +1,2 @@
+spring.batch.job.jdbccursorreader.name=fooReader
+spring.batch.job.jdbccursorreader.sql=select item_name from item_sample order by item_name
diff --git a/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-jdbcwriter.properties b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-jdbcwriter.properties
new file mode 100644
index 00000000..93aa0d38
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application-jdbcwriter.properties
@@ -0,0 +1,2 @@
+spring.batch.job.jdbcwriter.name=jdbcWriter
+spring.batch.job.jdbcwriter.sql=INSERT INTO item (item_name) VALUES (:ITEM_NAME)
diff --git a/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application.properties b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application.properties
new file mode 100644
index 00000000..ec7e797e
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+spring.application.name=Single Step Batch Job
+spring.batch.job.jobName=job
+spring.batch.job.stepName=step1
+spring.batch.job.chunkSize=5
diff --git a/spring-cloud-task-samples/single-step-batch-job/src/main/resources/test.txt b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/test.txt
new file mode 100644
index 00000000..ec5f7fe5
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/src/main/resources/test.txt
@@ -0,0 +1,6 @@
+foo
+bar
+baz
+qux
+boo
+Job
diff --git a/spring-cloud-task-samples/single-step-batch-job/src/test/java/io/spring/BatchJobApplicationTests.java b/spring-cloud-task-samples/single-step-batch-job/src/test/java/io/spring/BatchJobApplicationTests.java
new file mode 100644
index 00000000..5a185a17
--- /dev/null
+++ b/spring-cloud-task-samples/single-step-batch-job/src/test/java/io/spring/BatchJobApplicationTests.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2020-2020 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 io.spring;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+import org.h2.tools.Server;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.batch.test.AssertFile;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import org.springframework.util.SocketUtils;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Verifies that the SingleStepBatch Job for various scenarios are created properly.
+ *
+ * @author Glenn Renfro
+ */
+public class BatchJobApplicationTests {
+
+ private final static String DATASOURCE_URL;
+
+ private final static String DATASOURCE_USER_NAME = "SA";
+
+ private final static String DATASOURCE_USER_PASSWORD = "''";
+
+ private final static String DATASOURCE_DRIVER_CLASS_NAME = "org.h2.Driver";
+
+ private static int randomPort;
+
+ private static Server defaultServer;
+
+ static {
+ randomPort = SocketUtils.findAvailableTcpPort();
+ DATASOURCE_URL = "jdbc:h2:tcp://localhost:" + randomPort
+ + "/mem:dataflow;DB_CLOSE_DELAY=-1;" + "DB_CLOSE_ON_EXIT=FALSE";
+ }
+
+ private File outputFile;
+
+ @BeforeEach
+ public void setup() {
+ outputFile = new File("./result.txt");
+ initH2TCPServer();
+ }
+
+ @AfterEach
+ public void tearDown() throws Exception {
+ Files.deleteIfExists(Paths.get(outputFile.getAbsolutePath()));
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName(DATASOURCE_DRIVER_CLASS_NAME);
+ dataSource.setUrl(DATASOURCE_URL);
+ dataSource.setUsername(DATASOURCE_USER_NAME);
+ dataSource.setPassword(DATASOURCE_USER_PASSWORD);
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ jdbcTemplate.execute("TRUNCATE TABLE item");
+ jdbcTemplate.execute("DROP TABLE IF EXISTS BATCH_JOB_EXECUTION CASCADE");
+ jdbcTemplate.execute("DROP TABLE IF EXISTS BATCH_JOB_INSTANCE CASCADE");
+ }
+
+ @Test
+ public void testFileReaderJdbcWriter() throws Exception {
+ getSpringApplication().run(SingleStepBatchJobApplication.class,
+ "--spring.profiles.active=ffreader,jdbcwriter",
+ "--spring.datasource.username=" + DATASOURCE_USER_NAME,
+ "--spring.datasource.url=" + DATASOURCE_URL,
+ "--spring.datasource.driver-class-name=" + DATASOURCE_DRIVER_CLASS_NAME,
+ "--spring.datasource.password=" + DATASOURCE_USER_PASSWORD);
+ validateDBResult();
+ }
+
+ @Test
+ public void testJdbcReaderJdbcWriter() throws Exception {
+ getSpringApplication().run(SingleStepBatchJobApplication.class,
+ "--spring.profiles.active=jdbcreader,jdbcwriter",
+ "--spring.datasource.username=" + DATASOURCE_USER_NAME,
+ "--spring.datasource.url=" + DATASOURCE_URL,
+ "--spring.datasource.driver-class-name=" + DATASOURCE_DRIVER_CLASS_NAME,
+ "--spring.datasource.password=" + DATASOURCE_USER_PASSWORD);
+ validateDBResult();
+ }
+
+ @Test
+ public void testJdbcReaderFlatfileWriter() throws Exception {
+ getSpringApplication().run(SingleStepBatchJobApplication.class,
+ "--spring.profiles.active=jdbcreader,ffwriter",
+ "--spring.datasource.username=" + DATASOURCE_USER_NAME,
+ "--spring.datasource.url=" + DATASOURCE_URL,
+ "--spring.datasource.driver-class-name=" + DATASOURCE_DRIVER_CLASS_NAME,
+ "--spring.datasource.password=" + DATASOURCE_USER_PASSWORD);
+ validateFileResult();
+ }
+
+ @Test
+ public void testFileReaderFileWriter() throws Exception {
+ getSpringApplication().run(SingleStepBatchJobApplication.class,
+ "--spring.profiles.active=ffreader,ffwriter");
+ validateFileResult();
+ }
+
+ public Server initH2TCPServer() {
+ Server server = null;
+ try {
+ if (defaultServer == null) {
+ server = Server.createTcpServer("-ifNotExists", "-tcp",
+ "-tcpAllowOthers", "-tcpPort", String.valueOf(randomPort))
+ .start();
+ defaultServer = server;
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName(DATASOURCE_DRIVER_CLASS_NAME);
+ dataSource.setUrl(DATASOURCE_URL);
+ dataSource.setUsername(DATASOURCE_USER_NAME);
+ dataSource.setPassword(DATASOURCE_USER_PASSWORD);
+ ClassPathResource setupResource = new ClassPathResource(
+ "schema-h2.sql");
+ ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator(
+ setupResource);
+ resourceDatabasePopulator.execute(dataSource);
+ }
+ }
+ catch (SQLException e) {
+ throw new IllegalStateException(e);
+ }
+ return defaultServer;
+ }
+
+ private void validateFileResult() throws Exception{
+ AssertFile.assertLineCount(6, new FileSystemResource("./result.txt"));
+ AssertFile.assertFileEquals(new ClassPathResource("testresult.txt"),
+ new FileSystemResource(this.outputFile));
+ }
+
+ private void validateDBResult() {
+ DataSource dataSource = getDataSource();
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ List