diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/ErrorLogWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/ErrorLogTasklet.java
similarity index 94%
rename from spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/ErrorLogWriter.java
rename to spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/ErrorLogTasklet.java
index 5bcdc4d92..f466ad761 100644
--- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/ErrorLogWriter.java
+++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/ErrorLogTasklet.java
@@ -10,7 +10,7 @@ import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.core.AttributeAccessor;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
-public class ErrorLogWriter implements Tasklet {
+public class ErrorLogTasklet implements Tasklet {
protected final Log logger = LogFactory.getLog(getClass());
private SimpleJdbcTemplate simpleJdbcTemplate;
diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/player-containsBadRecords.csv b/spring-batch-samples/src/main/resources/data/footballjob/input/player-containsBadRecords.csv
new file mode 100644
index 000000000..c586f7440
--- /dev/null
+++ b/spring-batch-samples/src/main/resources/data/footballjob/input/player-containsBadRecords.csv
@@ -0,0 +1,20 @@
+AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996
+AbduRa00,Abdullah,Rabih,rb,1975,1999
+AberWa00,Abercrombie,Walter,rb,1959,1982
+AbraDa00,Abramowicz,Danny,wr,1945,1967
+AdamBo00,Adams,Bob,te,1946,1969
+AdamCh00,Adams,Charlie,wr,1979,2003
+AdamCu00,Adams,Curtis,rb,1962
+AdamGe00,Adams,George,rb,1962,1985
+AdamGr00,Adams,Grant,2000,2005
+AdamJo00,Adams,John,rb,1937,1959
+Adams,Michael,wr,1974,1997
+AdamMi01,Adamle,Mike,rb,1949,1971
+AdamTo00,Adams,Tony,qb,1950,1975
+AdamTo01,Adams,Tom,wr,1940,1962
+AdamTo02,Adamle,Tony,rb,,1950
+AdamWi00,Adams,Willie,wr,1956,1979
+AddaJo00,Addai,Joseph,1983,2006,rb
+AdkiJa00,Adkisson,James,te,1980,2005
+AdkiMa00,Adkins,Margene,wr,1947,1970
+AdkiSa00,Adkins,Sam,qb,1955,1977
diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/player-small.csv b/spring-batch-samples/src/main/resources/data/footballjob/input/player-small.csv
deleted file mode 100644
index df5c8256a..000000000
--- a/spring-batch-samples/src/main/resources/data/footballjob/input/player-small.csv
+++ /dev/null
@@ -1,5 +0,0 @@
-AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996
-AbduRa00,Abdullah,Rabih,rb,1975,1999
-AberWa00,Abercrombie,Walter,rb,1959,1982
-AbraDa00,Abramowicz,Danny,wr,1945,1967
-AdamBo00,Adams,Bob,te,1946,1969
diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/player-small1.csv b/spring-batch-samples/src/main/resources/data/footballjob/input/player-small1.csv
new file mode 100644
index 000000000..48464b030
--- /dev/null
+++ b/spring-batch-samples/src/main/resources/data/footballjob/input/player-small1.csv
@@ -0,0 +1,20 @@
+AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996
+AbduRa00,Abdullah,Rabih,rb,1975,1999
+AberWa00,Abercrombie,Walter,rb,1959,1982
+AbraDa00,Abramowicz,Danny,wr,1945,1967
+AdamBo00,Adams,Bob,te,1946,1969
+AdamCh00,Adams,Charlie,wr,1979,2003
+AdamCu00,Adams,Curtis,rb,1962,1985
+AdamGe00,Adams,George,rb,1962,1985
+AdamGr00,Adams,Grant,wr,2000,2005
+AdamJo00,Adams,John,rb,1937,1959
+AdamMi00,Adams,Michael,wr,1974,1997
+AdamMi01,Adamle,Mike,rb,1949,1971
+AdamTo00,Adams,Tony,qb,1950,1975
+AdamTo01,Adams,Tom,wr,1940,1962
+AdamTo02,Adamle,Tony,rb,1924,1950
+AdamWi00,Adams,Willie,wr,1956,1979
+AddaJo00,Addai,Joseph,rb,1983,2006
+AdkiJa00,Adkisson,James,te,1980,2005
+AdkiMa00,Adkins,Margene,wr,1947,1970
+AdkiSa00,Adkins,Sam,qb,1955,1977
diff --git a/spring-batch-samples/src/main/resources/data/footballjob/input/player-small2.csv b/spring-batch-samples/src/main/resources/data/footballjob/input/player-small2.csv
new file mode 100644
index 000000000..efcf90500
--- /dev/null
+++ b/spring-batch-samples/src/main/resources/data/footballjob/input/player-small2.csv
@@ -0,0 +1,20 @@
+AffhEr00,Affholter,Erik,wr,1966,1991
+AgeeTo00,Agee,Tommie,rb,1964,1988
+AikeSa00,Aiken,Sam,wr,1980,2003
+AikmTr00,Aikman,Troy,qb,1966,1989
+AkinFr00,Akins,Frank,rb,1919,1943
+AlbeFr00,Albert,Frankie,qb,1920,1950
+AldrBe00,Aldridge,Bennie,rb,1926,1950
+AlexCh00,Alexander,Charles,rb,1957,1979
+AlexDe00,Alexander,Derrick,wr,1971,1994
+AlexGl00,Alexander,Glenn,wr,1947,1970
+AlexJe00,Alexander,Jeff,rb,1965,1989
+AlexKe00,Alexander,Kevin,wr,1975,1996
+AlexMi00,Alexander,Mike,wr,1965,1989
+AlexRa00,Alexander,Ray,wr,1962,1984
+AlexRi00,Alexis,Rich,rb,1981,2005
+AlexSh00,Alexander,Shaun,rb,1977,2000
+AlexSt00,Alexander,Stephen,te,1975,1998
+AlfoBr00,Alford,Brian,wr,1975,1998
+AlfoBr01,Alford,Bruce,wr,1922,1950
+AlleAn00,Allen,Anthony,wr,1959,1985
diff --git a/spring-batch-samples/src/main/resources/incrementer-job-launcher-context.xml b/spring-batch-samples/src/main/resources/incrementer-job-launcher-context.xml
new file mode 100644
index 000000000..98b47f271
--- /dev/null
+++ b/spring-batch-samples/src/main/resources/incrementer-job-launcher-context.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-batch-samples/src/main/resources/jobs/footballJob.xml b/spring-batch-samples/src/main/resources/jobs/footballJob.xml
index d665d7894..341a474fa 100644
--- a/spring-batch-samples/src/main/resources/jobs/footballJob.xml
+++ b/spring-batch-samples/src/main/resources/jobs/footballJob.xml
@@ -143,7 +143,7 @@
games.file.name=games-small.csv
- player.file.name=player-small.csv
+ player.file.name=player-small1.csv
job.commit.interval=2
diff --git a/spring-batch-samples/src/main/resources/jobs/incrementerJob.xml b/spring-batch-samples/src/main/resources/jobs/incrementerJob.xml
new file mode 100644
index 000000000..1eed48314
--- /dev/null
+++ b/spring-batch-samples/src/main/resources/jobs/incrementerJob.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-batch-samples/src/main/resources/jobs/nonSequentialDecisionJob.xml b/spring-batch-samples/src/main/resources/jobs/nonSequentialDecisionJob.xml
index 09b7680d9..0435dc7f7 100644
--- a/spring-batch-samples/src/main/resources/jobs/nonSequentialDecisionJob.xml
+++ b/spring-batch-samples/src/main/resources/jobs/nonSequentialDecisionJob.xml
@@ -1,49 +1,34 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-batch-samples/src/main/resources/jobs/nonSequentialJob-base.xml b/spring-batch-samples/src/main/resources/jobs/nonSequentialJob-base.xml
index f967ae361..f81b19472 100644
--- a/spring-batch-samples/src/main/resources/jobs/nonSequentialJob-base.xml
+++ b/spring-batch-samples/src/main/resources/jobs/nonSequentialJob-base.xml
@@ -25,15 +25,16 @@
-
+
+
-
+
@@ -59,8 +60,12 @@
+
+
+
+
-
+
@@ -76,7 +81,7 @@
-
+
@@ -112,8 +117,6 @@
games.file.name=games-small.csv
-
- player.file.name=player-containsBadRecords.csv
job.commit.interval=2
diff --git a/spring-batch-samples/src/main/resources/jobs/nonSequentialJob.xml b/spring-batch-samples/src/main/resources/jobs/nonSequentialJob.xml
index 7c7d0c58c..b79b23f55 100644
--- a/spring-batch-samples/src/main/resources/jobs/nonSequentialJob.xml
+++ b/spring-batch-samples/src/main/resources/jobs/nonSequentialJob.xml
@@ -5,8 +5,10 @@
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.0.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+ xsi:schemaLocation="http://www.springframework.org/schema/batch
+ http://www.springframework.org/schema/batch/spring-batch-2.0.xsd
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
@@ -25,18 +27,4 @@
-
-
diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/IncrementerJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/IncrementerJobFunctionalTests.java
new file mode 100644
index 000000000..b24e416cb
--- /dev/null
+++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/IncrementerJobFunctionalTests.java
@@ -0,0 +1,105 @@
+package org.springframework.batch.sample;
+
+import static org.junit.Assert.*;
+
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.batch.core.launch.JobOperator;
+import org.springframework.batch.core.launch.JobParametersNotFoundException;
+import org.springframework.batch.core.launch.NoSuchJobException;
+import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
+import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
+import org.springframework.batch.core.repository.JobRestartException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.jdbc.SimpleJdbcTestUtils;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "/incrementer-job-launcher-context.xml" })
+public class IncrementerJobFunctionalTests {
+
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+
+ @Autowired
+ private JobOperator jobOperator;
+
+ /**
+ * This test calls the same job twice. However, using a job incrementer, the
+ * second launching is a separate job instance.
+ *
+ * Conditions:
+ *
+ * - Two flat files, each containing 20 player records
+ *
- Job is started twice, using the job incrementer to chose the input
+ * file.
+ *
+ * Expected Results:
+ *
+ * - First run completes with 20 players in the database
+ *
- Second run completes with 40 players in the database.
+ *
+ */
+ @Test
+ public void testWithSkips() throws Exception {
+ simpleJdbcTemplate.update("DELETE from PLAYERS");
+
+ long id1 = this.launchJob();
+ Map execution1 = this.getJobExecution(id1);
+ assertEquals("COMPLETED", execution1.get("STATUS"));
+ assertEquals(20, this.countPlayers());
+
+ long id2 = this.launchJob();
+ Map execution2 = this.getJobExecution(id2);
+ assertEquals("COMPLETED", execution2.get("STATUS"));
+ assertEquals(40, this.countPlayers());
+
+ assertTrue(id1 != id2);
+ assertTrue(!execution1.get("JOB_INSTANCE_ID").equals(execution2.get("JOB_INSTANCE_ID")));
+ }
+
+ private Map getJobExecution(long jobExecutionId) {
+ return simpleJdbcTemplate.queryForMap("SELECT * from BATCH_JOB_EXECUTION where JOB_EXECUTION_ID = ?",
+ jobExecutionId);
+ }
+
+ private int countPlayers() {
+ return SimpleJdbcTestUtils.countRowsInTable(simpleJdbcTemplate, "PLAYERS");
+ }
+
+ /**
+ * Launch the entire job, including all steps, in order.
+ *
+ * @return JobExecution, so that the test may validate the exit status
+ */
+ public long launchJob() {
+ try {
+ return this.jobOperator.startNextInstance("incrementerJob");
+ }
+ catch (NoSuchJobException e) {
+ throw new RuntimeException(e);
+ }
+ catch (JobExecutionAlreadyRunningException e) {
+ throw new RuntimeException(e);
+ }
+ catch (JobParametersNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ catch (JobRestartException e) {
+ throw new RuntimeException(e);
+ }
+ catch (JobInstanceAlreadyCompleteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Autowired
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ }
+}
diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialDecisionJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialDecisionJobFunctionalTests.java
index 2cd9a44bc..66abad61c 100644
--- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialDecisionJobFunctionalTests.java
+++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialDecisionJobFunctionalTests.java
@@ -1,40 +1,10 @@
package org.springframework.batch.sample;
-import static org.junit.Assert.assertEquals;
-
-import javax.sql.DataSource;
-
-import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.batch.core.BatchStatus;
-import org.springframework.batch.test.AbstractJobTests;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.jdbc.SimpleJdbcTestUtils;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/nonSequentialDecisionJob.xml" })
-public class NonSequentialDecisionJobFunctionalTests extends AbstractJobTests {
-
- private SimpleJdbcTemplate simpleJdbcTemplate;
-
- @Test
- public void testWithSkips() throws Exception {
- simpleJdbcTemplate.update("DELETE from ERROR_LOG");
- simpleJdbcTemplate.update("DELETE from PLAYER_SUMMARY");
- simpleJdbcTemplate.update("DELETE from PLAYERS");
- simpleJdbcTemplate.update("DELETE from GAMES");
-
- assertEquals(BatchStatus.COMPLETED, this.launchJob().getStatus());
-
- assertEquals(1, SimpleJdbcTestUtils.countRowsInTable(simpleJdbcTemplate, "ERROR_LOG"));
- assertEquals(9, SimpleJdbcTestUtils.countRowsInTable(simpleJdbcTemplate, "PLAYER_SUMMARY"));
- }
-
- @Autowired
- public void setDataSource(DataSource dataSource) {
- this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
- }
+public class NonSequentialDecisionJobFunctionalTests extends NonSequentialJobFunctionalTestsBase {
}
diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialJobFunctionalTests.java
index 58c0b2ff2..099f358c2 100644
--- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialJobFunctionalTests.java
+++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialJobFunctionalTests.java
@@ -1,41 +1,10 @@
package org.springframework.batch.sample;
-import static org.junit.Assert.assertEquals;
-
-import javax.sql.DataSource;
-
-import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.batch.core.BatchStatus;
-import org.springframework.batch.test.AbstractJobTests;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.jdbc.SimpleJdbcTestUtils;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/nonSequentialJob.xml" })
-public class NonSequentialJobFunctionalTests extends AbstractJobTests {
-
- private SimpleJdbcTemplate simpleJdbcTemplate;
-
- @Test
- public void testWithSkips() throws Exception {
-
- simpleJdbcTemplate.update("DELETE from ERROR_LOG");
- simpleJdbcTemplate.update("DELETE from PLAYER_SUMMARY");
- simpleJdbcTemplate.update("DELETE from PLAYERS");
- simpleJdbcTemplate.update("DELETE from GAMES");
-
- assertEquals(BatchStatus.COMPLETED, this.launchJob().getStatus());
-
- assertEquals(1, SimpleJdbcTestUtils.countRowsInTable(simpleJdbcTemplate, "ERROR_LOG"));
- assertEquals(9, SimpleJdbcTestUtils.countRowsInTable(simpleJdbcTemplate, "PLAYER_SUMMARY"));
- }
-
- @Autowired
- public void setDataSource(DataSource dataSource) {
- this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
- }
+public class NonSequentialJobFunctionalTests extends NonSequentialJobFunctionalTestsBase {
}
diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialJobFunctionalTestsBase.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialJobFunctionalTestsBase.java
new file mode 100644
index 000000000..1a28fc25b
--- /dev/null
+++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/NonSequentialJobFunctionalTestsBase.java
@@ -0,0 +1,89 @@
+package org.springframework.batch.sample;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.junit.Test;
+import org.springframework.batch.core.BatchStatus;
+import org.springframework.batch.core.JobParameter;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.test.AbstractJobTests;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+import org.springframework.test.jdbc.SimpleJdbcTestUtils;
+
+public abstract class NonSequentialJobFunctionalTestsBase extends AbstractJobTests {
+
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+
+ /**
+ * This test processes a file that contains bad records. Those records will
+ * skip. The step execution listener will detect that skips have occurred,
+ * and return an exit status that directs the flow job to the error logging
+ * step. The error logging step will log an error.
+ *
+ * Conditions:
+ *
+ * - Flat file containing 20 player records, 5 are invalid
+ *
- Skipping is allowed
+ *
+ * Expected Results:
+ *
+ * - 15 player records written to the database
+ *
- 1 error logged to the database
+ *
+ */
+ @Test
+ public void testWithSkips() throws Exception {
+ launchTest("player-containsBadRecords.csv");
+ assertEquals(1, SimpleJdbcTestUtils.countRowsInTable(simpleJdbcTemplate, "ERROR_LOG"));
+ assertEquals(15, SimpleJdbcTestUtils.countRowsInTable(simpleJdbcTemplate, "PLAYERS"));
+ }
+
+ /**
+ * This test processes a file that contains all valid record. The step
+ * execution listener will detect that NO skips have occurred, and return an
+ * exit status that direct the flow job to bypass the error logging step.
+ *
+ * Conditions:
+ *
+ * - Flat file containing 20 player records, all are valid
+ *
- Skipping is allowed
+ *
+ * Expected Results:
+ *
+ * - 20 player records written to the database
+ *
- NO errors logged to the database
+ *
+ */
+ @Test
+ public void testWithoutSkips() throws Exception {
+ launchTest("player-small1.csv");
+ assertEquals(0, SimpleJdbcTestUtils.countRowsInTable(simpleJdbcTemplate, "ERROR_LOG"));
+ assertEquals(20, SimpleJdbcTestUtils.countRowsInTable(simpleJdbcTemplate, "PLAYERS"));
+ }
+
+ private void launchTest(String playerInputfile) throws Exception {
+ simpleJdbcTemplate.update("DELETE from ERROR_LOG");
+ simpleJdbcTemplate.update("DELETE from PLAYER_SUMMARY");
+ simpleJdbcTemplate.update("DELETE from PLAYERS");
+ simpleJdbcTemplate.update("DELETE from GAMES");
+
+ Map parameters = new HashMap();
+ parameters.put("timestamp", new JobParameter(new Date().getTime()));
+ parameters.put("player.file.name", new JobParameter(playerInputfile));
+ JobParameters jobParameters = new JobParameters(parameters);
+
+ assertEquals(BatchStatus.COMPLETED, this.launchJob(jobParameters).getStatus());
+ }
+
+ @Autowired
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ }
+}