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> result = jdbcTemplate + .queryForList("SELECT item_name FROM item ORDER BY item_name"); + assertThat(result.size()).isEqualTo(6); + + assertThat(result.get(0).get("item_name")).isEqualTo("Job"); + assertThat(result.get(1).get("item_name")).isEqualTo("bar"); + assertThat(result.get(2).get("item_name")).isEqualTo("baz"); + assertThat(result.get(3).get("item_name")).isEqualTo("boo"); + assertThat(result.get(4).get("item_name")).isEqualTo("foo"); + assertThat(result.get(5).get("item_name")).isEqualTo("qux"); + } + + private DataSource getDataSource() { + DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); + dataSourceBuilder.driverClassName(DATASOURCE_DRIVER_CLASS_NAME); + dataSourceBuilder.url(DATASOURCE_URL); + dataSourceBuilder.username(DATASOURCE_USER_NAME); + dataSourceBuilder.password(DATASOURCE_USER_PASSWORD); + return dataSourceBuilder.build(); + } + private SpringApplication getSpringApplication() { + SpringApplication springApplication = new SpringApplication(); + Map properties = new HashMap<>(); + properties.put("spring.application.name", "Single Step Batch Job"); + properties.put("spring.batch.job.jobName", "job"); + properties.put("spring.batch.job.stepName", "step1"); + properties.put("spring.batch.job.chunkSize", "5"); + springApplication.setDefaultProperties(properties); + return springApplication; + } + +} diff --git a/spring-cloud-task-samples/single-step-batch-job/src/test/resources/schema-h2.sql b/spring-cloud-task-samples/single-step-batch-job/src/test/resources/schema-h2.sql new file mode 100644 index 00000000..fe7f50f7 --- /dev/null +++ b/spring-cloud-task-samples/single-step-batch-job/src/test/resources/schema-h2.sql @@ -0,0 +1,16 @@ +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'); diff --git a/spring-cloud-task-samples/single-step-batch-job/src/test/resources/test.txt b/spring-cloud-task-samples/single-step-batch-job/src/test/resources/test.txt new file mode 100644 index 00000000..c2507739 --- /dev/null +++ b/spring-cloud-task-samples/single-step-batch-job/src/test/resources/test.txt @@ -0,0 +1,6 @@ +Job +bar +baz +boo +foo +qux diff --git a/spring-cloud-task-samples/single-step-batch-job/src/test/resources/testresult.txt b/spring-cloud-task-samples/single-step-batch-job/src/test/resources/testresult.txt new file mode 100644 index 00000000..87a54d65 Binary files /dev/null and b/spring-cloud-task-samples/single-step-batch-job/src/test/resources/testresult.txt differ