diff --git a/core/src/main/java/org/springframework/batch/core/domain/JobExecution.java b/core/src/main/java/org/springframework/batch/core/domain/JobExecution.java index f26da2841..bf364831f 100644 --- a/core/src/main/java/org/springframework/batch/core/domain/JobExecution.java +++ b/core/src/main/java/org/springframework/batch/core/domain/JobExecution.java @@ -21,6 +21,7 @@ import java.util.Collection; import java.util.HashSet; import org.springframework.batch.core.runtime.JobIdentifier; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.RepeatContext; /** @@ -45,7 +46,7 @@ public class JobExecution extends Entity { private Timestamp endTime = null; - private String exitCode = ""; + private ExitStatus exitStatus = ExitStatus.UNKNOWN; // Package private constructor for Hibernate JobExecution() { @@ -110,17 +111,17 @@ public class JobExecution extends Entity { } /** - * @param exitCode + * @param exitStatus */ - public void setExitCode(String exitCode) { - this.exitCode = exitCode; + public void setExitStatus(ExitStatus exitStatus) { + this.exitStatus = exitStatus; } /** * @return the exitCode */ - public String getExitCode() { - return exitCode; + public ExitStatus getExitStatus() { + return exitStatus; } /** @@ -130,7 +131,7 @@ public class JobExecution extends Entity { * be multiple active contexts. * * @return all the chunk contexts that have been registered and not - * unregistered. A collection opf {@link RepeatContext} objects. + * unregistered. A collection of {@link RepeatContext} objects. */ public Collection getChunkContexts() { synchronized (chunkContexts) { diff --git a/core/src/main/java/org/springframework/batch/core/domain/StepExecution.java b/core/src/main/java/org/springframework/batch/core/domain/StepExecution.java index 22509d766..dcbcd9b87 100644 --- a/core/src/main/java/org/springframework/batch/core/domain/StepExecution.java +++ b/core/src/main/java/org/springframework/batch/core/domain/StepExecution.java @@ -19,6 +19,8 @@ package org.springframework.batch.core.domain; import java.sql.Timestamp; import java.util.Properties; +import org.springframework.batch.repeat.ExitStatus; + /** * Batch domain object representation the execution of a step. Unlike * JobExecution, there are four additional properties: luwCount, commitCount, @@ -51,10 +53,8 @@ public class StepExecution extends Entity { private Properties statistics = new Properties(); - private String exitCode = ""; + private ExitStatus exitStatus = ExitStatus.UNKNOWN; - private String exitDescription = ""; - private Throwable exception; /** @@ -199,17 +199,17 @@ public class StepExecution extends Entity { /** - * @param exitCode + * @param exitStatus */ - public void setExitCode(String exitCode) { - this.exitCode = exitCode; + public void setExitStatus(ExitStatus exitStatus) { + this.exitStatus = exitStatus; } /** * @return the exitCode */ - public String getExitCode() { - return exitCode; + public ExitStatus getExitStatus() { + return exitStatus; } public void setException(Throwable exception) { @@ -219,14 +219,6 @@ public class StepExecution extends Entity { public Throwable getException() { return exception; } - - public void setExitDescription(String exitDescription) { - this.exitDescription = exitDescription; - } - - public String getExitDescription() { - return exitDescription; - } /** * Accessor for the step governing this execution. diff --git a/core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java b/core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java index 6c54a8056..a1db22568 100644 --- a/core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java +++ b/core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java @@ -20,6 +20,7 @@ import java.sql.Timestamp; import junit.framework.TestCase; import org.springframework.batch.core.runtime.SimpleJobIdentifier; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.repeat.context.RepeatContextSupport; /** @@ -75,12 +76,27 @@ public class JobExecutionTests extends TestCase { } /** - * Test method for {@link org.springframework.batch.core.domain.JobExecution#getExitCode()}. + * Test method for {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. + */ + public void testGetJobIdForNullJob() { + execution = new JobExecution(null); + assertEquals(null, execution.getJobId()); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. + */ + public void testGetJob() { + assertNotNull(execution.getJob()); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.JobExecution#getExitStatus()}. */ public void testGetExitCode() { - assertEquals("", execution.getExitCode()); - execution.setExitCode("23"); - assertEquals("23", execution.getExitCode()); + assertEquals(ExitStatus.UNKNOWN, execution.getExitStatus()); + execution.setExitStatus(new ExitStatus(true, "23")); + assertEquals("23", execution.getExitStatus().getExitCode()); } public void testContextContainsInfo() throws Exception { diff --git a/core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java b/core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java index f8aab34c1..ab1387823 100644 --- a/core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java +++ b/core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java @@ -18,6 +18,8 @@ package org.springframework.batch.core.domain; import java.sql.Timestamp; import java.util.Properties; +import org.springframework.batch.repeat.ExitStatus; + import junit.framework.TestCase; /** @@ -77,12 +79,12 @@ public class StepExecutionTests extends TestCase { /** * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getExitCode()}. + * {@link org.springframework.batch.core.domain.JobExecution#getExitStatus()}. */ public void testGetExitCode() { - assertEquals("", execution.getExitCode()); - execution.setExitCode("23"); - assertEquals("23", execution.getExitCode()); + assertEquals(ExitStatus.UNKNOWN, execution.getExitStatus()); + execution.setExitStatus(ExitStatus.FINISHED); + assertEquals(ExitStatus.FINISHED, execution.getExitStatus()); } /** diff --git a/dictionary.txt b/dictionary.txt index 6cbf677cc..b05df35be 100644 --- a/dictionary.txt +++ b/dictionary.txt @@ -47,3 +47,4 @@ incrementer hoc unbind tasklet +bespoke diff --git a/execution/src/main/java/org/springframework/batch/execution/job/DefaultJobExecutor.java b/execution/src/main/java/org/springframework/batch/execution/job/DefaultJobExecutor.java index 4e4fe3f30..a5d185292 100644 --- a/execution/src/main/java/org/springframework/batch/execution/job/DefaultJobExecutor.java +++ b/execution/src/main/java/org/springframework/batch/execution/job/DefaultJobExecutor.java @@ -93,7 +93,7 @@ public class DefaultJobExecutor implements JobExecutor { } finally { jobExecution.setEndTime(new Timestamp(System.currentTimeMillis())); - jobExecution.setExitCode(status.getExitCode()); + jobExecution.setExitStatus(status); jobRepository.saveOrUpdate(jobExecution); } diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/ExitStatusUserType.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/ExitStatusUserType.java new file mode 100644 index 000000000..bb043fe22 --- /dev/null +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/ExitStatusUserType.java @@ -0,0 +1,72 @@ +/* + * Copyright 2006-2007 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 + * + * http://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.batch.execution.repository.dao; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; + +import org.hibernate.HibernateException; +import org.springframework.batch.repeat.ExitStatus; + +/** + * User type object to help Hibernate persist (@link {@link ExitStatus}) + * objects. The continuable flag is mapped to a String with value Y/N. + * + * @author Dave Syer + * + */ +public class ExitStatusUserType extends ImmutableValueUserType { + + /** + * Convert a result set to an {@link ExitStatus}. + * + * @see org.springframework.batch.execution.repository.dao.ImmutableValueUserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object) + */ + public Object nullSafeGet(ResultSet rs, String[] names, Object owner) + throws HibernateException, SQLException { + boolean continuable = "Y".equals(rs.getString(names[0])); + String code = rs.getString(names[1]); + String message = rs.getString(names[2]); + return new ExitStatus(continuable, code, message); + } + + /** + * Convert the value (as an {@link ExitStatus}) to the columns in the + * prepared statement. + * + * @see org.springframework.batch.execution.repository.dao.ImmutableValueUserType#nullSafeSet(java.sql.PreparedStatement, + * java.lang.Object, int) + */ + public void nullSafeSet(PreparedStatement st, Object value, int index) + throws HibernateException, SQLException { + ExitStatus status = (ExitStatus) value; + st.setString(index, status.isContinuable() ? "Y" : "N"); + st.setString(index + 1, status.getExitCode()); + st.setString(index + 2, status.getExitDescription()); + } + + public Class returnedClass() { + return ExitStatus.class; + } + + public int[] sqlTypes() { + return new int[] { Types.CHAR, Types.VARCHAR, Types.VARCHAR }; + } + +} diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/ImmutableValueUserType.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/ImmutableValueUserType.java new file mode 100644 index 000000000..03af04085 --- /dev/null +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/ImmutableValueUserType.java @@ -0,0 +1,62 @@ +package org.springframework.batch.execution.repository.dao; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.hibernate.HibernateException; +import org.hibernate.usertype.UserType; + +/** + * A base class for user types that map immutable values (objects that cannot be + * changed after construction and may be safely shared). + * + * @author Ben Hale + * @author Dave Syer + */ +public abstract class ImmutableValueUserType implements UserType { + + public Object assemble(Serializable cached, Object owner) + throws HibernateException { + return cached; + } + + public Object deepCopy(Object value) throws HibernateException { + return value; + } + + public Serializable disassemble(Object value) throws HibernateException { + return (Serializable) value; + } + + public boolean equals(Object x, Object y) throws HibernateException { + return x.equals(y); + } + + public int hashCode(Object x) throws HibernateException { + return x.hashCode(); + } + + public boolean isMutable() { + return false; + } + + public Object replace(Object original, Object target, Object owner) + throws HibernateException { + return original; + } + + // subclasses must implement the following methods + + public abstract Class returnedClass(); + + public abstract int[] sqlTypes(); + + public abstract Object nullSafeGet(ResultSet rs, String[] names, + Object owner) throws HibernateException, SQLException; + + public abstract void nullSafeSet(PreparedStatement st, Object value, + int index) throws HibernateException, SQLException; + +} diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java index 01c5ebb7e..35f5fc05f 100644 --- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java @@ -26,6 +26,7 @@ import org.springframework.batch.core.domain.JobInstance; import org.springframework.batch.core.repository.NoSuchBatchDomainObjectException; import org.springframework.batch.core.runtime.JobIdentifier; import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.beans.factory.InitializingBean; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; @@ -69,10 +70,10 @@ public class SqlJobDao implements JobDao, InitializingBean { // Job Execution SqlStatements private static final String UPDATE_JOB_EXECUTION = "UPDATE %PREFIX%JOB_EXECUTION set START_TIME = ?, END_TIME = ?, " - + " STATUS = ?, EXIT_CODE = ? where ID = ?"; + + " STATUS = ?, CONTINUABLE = ?, EXIT_CODE = ?, EXIT_MESSAGE = ? where ID = ?"; private static final String SAVE_JOB_EXECUTION = "INSERT into %PREFIX%JOB_EXECUTION(ID, JOB_ID, START_TIME, " - + "END_TIME, STATUS, EXIT_CODE) values (?, ?, ?, ?, ?, ?)"; + + "END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) values (?, ?, ?, ?, ?, ?, ?, ?)"; private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE ID=?"; @@ -187,7 +188,9 @@ public class SqlJobDao implements JobDao, InitializingBean { Object[] parameters = new Object[] { jobExecution.getId(), jobExecution.getJobId(), jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(), - jobExecution.getExitCode() }; + jobExecution.getExitStatus().isContinuable() ? "Y" : "N", + jobExecution.getExitStatus().getExitCode(), + jobExecution.getExitStatus().getExitDescription() }; jdbcTemplate.update(getSaveJobExecutionQuery(), parameters); } @@ -205,7 +208,10 @@ public class SqlJobDao implements JobDao, InitializingBean { Object[] parameters = new Object[] { jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(), - jobExecution.getExitCode(), jobExecution.getId() }; + jobExecution.getExitStatus().isContinuable() ? "Y" : "N", + jobExecution.getExitStatus().getExitCode(), + jobExecution.getExitStatus().getExitDescription(), + jobExecution.getId() }; if (jobExecution.getId() == null) { throw new IllegalArgumentException( @@ -246,7 +252,8 @@ public class SqlJobDao implements JobDao, InitializingBean { Assert.notNull(job, "Job cannot be null."); Assert.notNull(job.getId(), "Job Id cannot be null."); - return jdbcTemplate.query(getQuery(JobExecutionRowMapper.FIND_JOB_EXECUTIONS), + return jdbcTemplate.query( + getQuery(JobExecutionRowMapper.FIND_JOB_EXECUTIONS), new Object[] { job.getId() }, new JobExecutionRowMapper(job)); } @@ -366,16 +373,17 @@ public class SqlJobDao implements JobDao, InitializingBean { /** * Re-usable mapper for {@link JobExecution} instances. + * * @author Dave Syer - * + * */ public static class JobExecutionRowMapper implements RowMapper { - - public static final String FIND_JOB_EXECUTIONS = "SELECT ID, START_TIME, END_TIME, STATUS from %PREFIX%JOB_EXECUTION" - + " where JOB_ID = ?"; - public static final String GET_JOB_EXECUTION = "SELECT ID, START_TIME, END_TIME, STATUS from %PREFIX%JOB_EXECUTION" - + " where ID = ?"; + public static final String FIND_JOB_EXECUTIONS = "SELECT ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION" + + " where JOB_ID = ?"; + + public static final String GET_JOB_EXECUTION = "SELECT ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION" + + " where ID = ?"; private JobInstance job; @@ -390,6 +398,8 @@ public class SqlJobDao implements JobDao, InitializingBean { jobExecution.setStartTime(rs.getTimestamp(2)); jobExecution.setEndTime(rs.getTimestamp(3)); jobExecution.setStatus(BatchStatus.getStatus(rs.getString(4))); + jobExecution.setExitStatus(new ExitStatus("Y".equals(rs + .getString(5)), rs.getString(6), rs.getString(7))); return jobExecution; } diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java index 0ac56dda9..ff87f3ef0 100644 --- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java @@ -28,6 +28,7 @@ import org.springframework.batch.core.domain.StepExecution; import org.springframework.batch.core.domain.StepInstance; import org.springframework.batch.core.repository.NoSuchBatchDomainObjectException; import org.springframework.batch.execution.repository.dao.SqlJobDao.JobExecutionRowMapper; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.restart.GenericRestartData; import org.springframework.batch.restart.RestartData; import org.springframework.batch.support.PropertiesConverter; @@ -69,18 +70,18 @@ public class SqlStepDao implements StepDao, InitializingBean { // StepExecution statements private static final String SAVE_STEP_EXECUTION = "INSERT into %PREFIX%STEP_EXECUTION(ID, VERSION, STEP_ID, JOB_EXECUTION_ID, START_TIME, " - + "END_TIME, STATUS, COMMIT_COUNT, TASK_COUNT, TASK_STATISTICS, EXIT_CODE, EXIT_MESSAGE) " - + "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + "END_TIME, STATUS, COMMIT_COUNT, TASK_COUNT, TASK_STATISTICS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) " + + "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; private static final String UPDATE_STEP_EXECUTION = "UPDATE %PREFIX%STEP_EXECUTION set START_TIME = ?, END_TIME = ?, " - + "STATUS = ?, COMMIT_COUNT = ?, TASK_COUNT = ?, TASK_STATISTICS = ?, EXIT_CODE = ?, " + + "STATUS = ?, COMMIT_COUNT = ?, TASK_COUNT = ?, TASK_STATISTICS = ?, CONTINUABLE = ? , EXIT_CODE = ?, " + "EXIT_MESSAGE = ? where ID = ?"; private static final String GET_STEP_EXECUTION_COUNT = "SELECT count(ID) from %PREFIX%STEP_EXECUTION where " + "STEP_ID = ?"; private static final String FIND_STEP_EXECUTIONS = "SELECT ID, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT," - + " TASK_COUNT, TASK_STATISTICS, EXIT_CODE, EXIT_MESSAGE from %PREFIX%STEP_EXECUTION where STEP_ID = ?"; + + " TASK_COUNT, TASK_STATISTICS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%STEP_EXECUTION where STEP_ID = ?"; private JdbcOperations jdbcTemplate; @@ -108,7 +109,8 @@ public class SqlStepDao implements StepDao, InitializingBean { * Injection setter for job dao. Used to save {@link JobExecution} * instances. * - * @param jobDao a {@link JobDao} + * @param jobDao + * a {@link JobDao} */ public void setJobDao(JobDao jobDao) { this.jobDao = jobDao; @@ -270,8 +272,10 @@ public class SqlStepDao implements StepDao, InitializingBean { stepExecution.getCommitCount(), stepExecution.getTaskCount(), PropertiesConverter.propertiesToString(stepExecution - .getStatistics()), stepExecution.getExitCode(), - stepExecution.getExitDescription() }; + .getStatistics()), + stepExecution.getExitStatus().isContinuable() ? "Y" : "N", + stepExecution.getExitStatus().getExitCode(), + stepExecution.getExitStatus().getExitDescription() }; jdbcTemplate.update(getQuery(SAVE_STEP_EXECUTION), parameters); } @@ -309,8 +313,11 @@ public class SqlStepDao implements StepDao, InitializingBean { stepExecution.getCommitCount(), stepExecution.getTaskCount(), PropertiesConverter.propertiesToString(stepExecution - .getStatistics()), stepExecution.getExitCode(), - stepExecution.getExitDescription(), stepExecution.getId() }; + .getStatistics()), + stepExecution.getExitStatus().isContinuable() ? "Y" : "N", + stepExecution.getExitStatus().getExitCode(), + stepExecution.getExitStatus().getExitDescription(), + stepExecution.getId() }; jdbcTemplate.update(getQuery(UPDATE_STEP_EXECUTION), parameters); } @@ -355,8 +362,8 @@ public class SqlStepDao implements StepDao, InitializingBean { stepExecution.setTaskCount(rs.getInt(7)); stepExecution.setStatistics(PropertiesConverter .stringToProperties(rs.getString(8))); - stepExecution.setExitCode(rs.getString(9)); - stepExecution.setExitDescription(rs.getString(10)); + stepExecution.setExitStatus(new ExitStatus("Y".equals(rs + .getString(9)), rs.getString(10), rs.getString(11))); return stepExecution; } }; diff --git a/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java b/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java index c35110475..86d97913e 100644 --- a/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java +++ b/execution/src/main/java/org/springframework/batch/execution/step/simple/SimpleStepExecutor.java @@ -266,8 +266,7 @@ public class SimpleStepExecutor implements StepExecutor { } finally { - stepExecution.setExitCode(status.getExitCode()); - stepExecution.setExitDescription(status.getExitDescription()); + stepExecution.setExitStatus(status); stepExecution.setEndTime(new Timestamp(System.currentTimeMillis())); try { jobRepository.saveOrUpdate(stepExecution); diff --git a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobExecution.hbm.xml b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobExecution.hbm.xml index 90b066021..33133314b 100644 --- a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobExecution.hbm.xml +++ b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobExecution.hbm.xml @@ -16,7 +16,11 @@ - + + + + + diff --git a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepExecution.hbm.xml b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepExecution.hbm.xml index 8c6ee24b4..67e836399 100644 --- a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepExecution.hbm.xml +++ b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepExecution.hbm.xml @@ -20,7 +20,11 @@ - + + + + + diff --git a/execution/src/main/resources/schema-db2.sql b/execution/src/main/resources/schema-db2.sql deleted file mode 100644 index 32d0e22ed..000000000 --- a/execution/src/main/resources/schema-db2.sql +++ /dev/null @@ -1,56 +0,0 @@ --- Autogenerated: do not edit this file -DROP TABLE BATCH_STEP_EXECUTION ; -DROP TABLE BATCH_JOB_EXECUTION ; -DROP TABLE BATCH_STEP ; -DROP TABLE BATCH_JOB ; - -DROP SEQUENCE BATCH_STEP_EXECUTION_SEQ ; -DROP SEQUENCE BATCH_STEP_SEQ ; -DROP SEQUENCE BATCH_JOB_EXECUTION_SEQ ; -DROP SEQUENCE BATCH_JOB_SEQ ; - --- Autogenerated: do not edit this file -CREATE TABLE BATCH_JOB ( - ID BIGINT PRIMARY KEY NOT NULL, - VERSION BIGINT, - JOB_NAME VARCHAR(100) NOT NULL , - JOB_STREAM VARCHAR(20) , - SCHEDULE_DATE DATE , - JOB_RUN CHAR(2), - STATUS VARCHAR(10) ); - -CREATE TABLE BATCH_JOB_EXECUTION ( - ID BIGINT PRIMARY KEY NOT NULL, - VERSION BIGINT, - JOB_ID BIGINT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - EXIT_CODE VARCHAR(250)); - -CREATE TABLE BATCH_STEP ( - ID BIGINT PRIMARY KEY NOT NULL, - VERSION BIGINT, - JOB_ID BIGINT NOT NULL, - STEP_NAME VARCHAR(100) NOT NULL, - STATUS VARCHAR(10), - RESTART_DATA VARCHAR(200)); - -CREATE TABLE BATCH_STEP_EXECUTION ( - ID BIGINT PRIMARY KEY NOT NULL, - VERSION BIGINT NOT NULL, - STEP_ID BIGINT NOT NULL, - JOB_EXECUTION_ID BIGINT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - COMMIT_COUNT BIGINT , - TASK_COUNT BIGINT , - TASK_STATISTICS VARCHAR(250), - EXIT_CODE VARCHAR(250), - EXIT_MESSAGE VARCHAR(250)); - -CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; -CREATE SEQUENCE BATCH_STEP_SEQ; -CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ; -CREATE SEQUENCE BATCH_JOB_SEQ; diff --git a/execution/src/main/resources/schema-derby.sql b/execution/src/main/resources/schema-derby.sql deleted file mode 100644 index bf2f8d700..000000000 --- a/execution/src/main/resources/schema-derby.sql +++ /dev/null @@ -1,56 +0,0 @@ --- Autogenerated: do not edit this file -DROP TABLE BATCH_STEP_EXECUTION ; -DROP TABLE BATCH_JOB_EXECUTION ; -DROP TABLE BATCH_STEP ; -DROP TABLE BATCH_JOB ; - -DROP SEQUENCE BATCH_STEP_EXECUTION_SEQ ; -DROP SEQUENCE BATCH_STEP_SEQ ; -DROP SEQUENCE BATCH_JOB_EXECUTION_SEQ ; -DROP SEQUENCE BATCH_JOB_SEQ ; - --- Autogenerated: do not edit this file -CREATE TABLE BATCH_JOB ( - ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, - VERSION BIGINT, - JOB_NAME VARCHAR(100) NOT NULL , - JOB_STREAM VARCHAR(20) , - SCHEDULE_DATE DATE , - JOB_RUN CHAR(2), - STATUS VARCHAR(10) ); - -CREATE TABLE BATCH_JOB_EXECUTION ( - ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, - VERSION BIGINT, - JOB_ID BIGINT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - EXIT_CODE VARCHAR(250)); - -CREATE TABLE BATCH_STEP ( - ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, - VERSION BIGINT, - JOB_ID BIGINT NOT NULL, - STEP_NAME VARCHAR(100) NOT NULL, - STATUS VARCHAR(10), - RESTART_DATA VARCHAR(200)); - -CREATE TABLE BATCH_STEP_EXECUTION ( - ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, - VERSION BIGINT NOT NULL, - STEP_ID BIGINT NOT NULL, - JOB_EXECUTION_ID BIGINT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - COMMIT_COUNT BIGINT , - TASK_COUNT BIGINT , - TASK_STATISTICS VARCHAR(250), - EXIT_CODE VARCHAR(250), - EXIT_MESSAGE VARCHAR(250)); - -CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; -CREATE SEQUENCE BATCH_STEP_SEQ; -CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ; -CREATE SEQUENCE BATCH_JOB_SEQ; diff --git a/execution/src/main/resources/schema-hsqldb.sql b/execution/src/main/resources/schema-hsqldb.sql deleted file mode 100644 index 297529fdb..000000000 --- a/execution/src/main/resources/schema-hsqldb.sql +++ /dev/null @@ -1,64 +0,0 @@ --- Autogenerated: do not edit this file -DROP TABLE BATCH_STEP_EXECUTION IF EXISTS; -DROP TABLE BATCH_JOB_EXECUTION IF EXISTS; -DROP TABLE BATCH_STEP IF EXISTS; -DROP TABLE BATCH_JOB IF EXISTS; - -DROP TABLE BATCH_STEP_EXECUTION_SEQ IF EXISTS; -DROP TABLE BATCH_STEP_SEQ IF EXISTS; -DROP TABLE BATCH_JOB_EXECUTION_SEQ IF EXISTS; -DROP TABLE BATCH_JOB_SEQ IF EXISTS; - --- Autogenerated: do not edit this file -CREATE TABLE BATCH_JOB ( - ID BIGINT IDENTITY PRIMARY KEY , - VERSION BIGINT, - JOB_NAME VARCHAR(100) NOT NULL , - JOB_STREAM VARCHAR(20) , - SCHEDULE_DATE DATE , - JOB_RUN CHAR(2), - STATUS VARCHAR(10) ); - -CREATE TABLE BATCH_JOB_EXECUTION ( - ID BIGINT IDENTITY PRIMARY KEY , - VERSION BIGINT, - JOB_ID BIGINT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - EXIT_CODE VARCHAR(250)); - -CREATE TABLE BATCH_STEP ( - ID BIGINT IDENTITY PRIMARY KEY , - VERSION BIGINT, - JOB_ID BIGINT NOT NULL, - STEP_NAME VARCHAR(100) NOT NULL, - STATUS VARCHAR(10), - RESTART_DATA VARCHAR(200)); - -CREATE TABLE BATCH_STEP_EXECUTION ( - ID BIGINT IDENTITY PRIMARY KEY , - VERSION BIGINT NOT NULL, - STEP_ID BIGINT NOT NULL, - JOB_EXECUTION_ID BIGINT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - COMMIT_COUNT BIGINT , - TASK_COUNT BIGINT , - TASK_STATISTICS VARCHAR(250), - EXIT_CODE VARCHAR(250), - EXIT_MESSAGE VARCHAR(250)); - -CREATE TABLE BATCH_STEP_EXECUTION_SEQ ( - ID BIGINT IDENTITY -); -CREATE TABLE BATCH_STEP_SEQ ( - ID BIGINT IDENTITY -); -CREATE TABLE BATCH_JOB_EXECUTION_SEQ ( - ID BIGINT IDENTITY -); -CREATE TABLE BATCH_JOB_SEQ ( - ID BIGINT IDENTITY -); diff --git a/execution/src/main/resources/schema-oracle10g.sql b/execution/src/main/resources/schema-oracle10g.sql deleted file mode 100644 index 038a1d6c2..000000000 --- a/execution/src/main/resources/schema-oracle10g.sql +++ /dev/null @@ -1,56 +0,0 @@ --- Autogenerated: do not edit this file -DROP TABLE BATCH_STEP_EXECUTION ; -DROP TABLE BATCH_JOB_EXECUTION ; -DROP TABLE BATCH_STEP ; -DROP TABLE BATCH_JOB ; - -DROP SEQUENCE BATCH_STEP_EXECUTION_SEQ ; -DROP SEQUENCE BATCH_STEP_SEQ ; -DROP SEQUENCE BATCH_JOB_EXECUTION_SEQ ; -DROP SEQUENCE BATCH_JOB_SEQ ; - --- Autogenerated: do not edit this file -CREATE TABLE BATCH_JOB ( - ID INT PRIMARY KEY , - VERSION INT, - JOB_NAME VARCHAR(100) NOT NULL , - JOB_STREAM VARCHAR(20) , - SCHEDULE_DATE DATE , - JOB_RUN CHAR(2), - STATUS VARCHAR(10) ); - -CREATE TABLE BATCH_JOB_EXECUTION ( - ID INT PRIMARY KEY , - VERSION INT, - JOB_ID INT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - EXIT_CODE VARCHAR(250)); - -CREATE TABLE BATCH_STEP ( - ID INT PRIMARY KEY , - VERSION INT, - JOB_ID INT NOT NULL, - STEP_NAME VARCHAR(100) NOT NULL, - STATUS VARCHAR(10), - RESTART_DATA VARCHAR(200)); - -CREATE TABLE BATCH_STEP_EXECUTION ( - ID INT PRIMARY KEY , - VERSION INT NOT NULL, - STEP_ID INT NOT NULL, - JOB_EXECUTION_ID INT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - COMMIT_COUNT INT , - TASK_COUNT INT , - TASK_STATISTICS VARCHAR(250), - EXIT_CODE VARCHAR(250), - EXIT_MESSAGE VARCHAR(250)); - -CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; -CREATE SEQUENCE BATCH_STEP_SEQ; -CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ; -CREATE SEQUENCE BATCH_JOB_SEQ; diff --git a/execution/src/main/resources/schema-postgresql.sql b/execution/src/main/resources/schema-postgresql.sql deleted file mode 100644 index 638ab009c..000000000 --- a/execution/src/main/resources/schema-postgresql.sql +++ /dev/null @@ -1,56 +0,0 @@ --- Autogenerated: do not edit this file -DROP TABLE BATCH_STEP_EXECUTION ; -DROP TABLE BATCH_JOB_EXECUTION ; -DROP TABLE BATCH_STEP ; -DROP TABLE BATCH_JOB ; - -DROP SEQUENCE BATCH_STEP_EXECUTION_SEQ ; -DROP SEQUENCE BATCH_STEP_SEQ ; -DROP SEQUENCE BATCH_JOB_EXECUTION_SEQ ; -DROP SEQUENCE BATCH_JOB_SEQ ; - --- Autogenerated: do not edit this file -CREATE TABLE BATCH_JOB ( - ID BIGINT PRIMARY KEY , - VERSION BIGINT, - JOB_NAME VARCHAR(100) NOT NULL , - JOB_STREAM VARCHAR(20) , - SCHEDULE_DATE DATE , - JOB_RUN CHAR(2), - STATUS VARCHAR(10) ); - -CREATE TABLE BATCH_JOB_EXECUTION ( - ID BIGINT PRIMARY KEY , - VERSION BIGINT, - JOB_ID BIGINT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - EXIT_CODE VARCHAR(250)); - -CREATE TABLE BATCH_STEP ( - ID BIGINT PRIMARY KEY , - VERSION BIGINT, - JOB_ID BIGINT NOT NULL, - STEP_NAME VARCHAR(100) NOT NULL, - STATUS VARCHAR(10), - RESTART_DATA VARCHAR(200)); - -CREATE TABLE BATCH_STEP_EXECUTION ( - ID BIGINT PRIMARY KEY , - VERSION BIGINT NOT NULL, - STEP_ID BIGINT NOT NULL, - JOB_EXECUTION_ID BIGINT NOT NULL, - START_TIME TIMESTAMP NOT NULL , - END_TIME TIMESTAMP , - STATUS VARCHAR(10), - COMMIT_COUNT BIGINT , - TASK_COUNT BIGINT , - TASK_STATISTICS VARCHAR(250), - EXIT_CODE VARCHAR(250), - EXIT_MESSAGE VARCHAR(250)); - -CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; -CREATE SEQUENCE BATCH_STEP_SEQ; -CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ; -CREATE SEQUENCE BATCH_JOB_SEQ; diff --git a/execution/src/main/sql/init.sql.vpp b/execution/src/main/sql/init.sql.vpp index b2c29a1ec..31e5ce40f 100644 --- a/execution/src/main/sql/init.sql.vpp +++ b/execution/src/main/sql/init.sql.vpp @@ -15,7 +15,9 @@ CREATE TABLE BATCH_JOB_EXECUTION ( START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , STATUS VARCHAR(10), - EXIT_CODE VARCHAR(250)); + CONTINUABLE CHAR(1), + EXIT_CODE VARCHAR(20), + EXIT_MESSAGE VARCHAR(250)); CREATE TABLE BATCH_STEP ( ID ${BIGINT} $!{IDENTITY} PRIMARY KEY $!{GENERATED}, @@ -36,7 +38,8 @@ CREATE TABLE BATCH_STEP_EXECUTION ( COMMIT_COUNT ${BIGINT} , TASK_COUNT ${BIGINT} , TASK_STATISTICS VARCHAR(250), - EXIT_CODE VARCHAR(250), + CONTINUABLE CHAR(1), + EXIT_CODE VARCHAR(20), EXIT_MESSAGE VARCHAR(250)); #sequence( "BATCH_STEP_EXECUTION_SEQ" ) diff --git a/execution/src/test/java/org/springframework/batch/execution/job/DefaultJobExecutorTests.java b/execution/src/test/java/org/springframework/batch/execution/job/DefaultJobExecutorTests.java index 171e765a0..7766df935 100644 --- a/execution/src/test/java/org/springframework/batch/execution/job/DefaultJobExecutorTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/job/DefaultJobExecutorTests.java @@ -174,7 +174,7 @@ public class DefaultJobExecutorTests extends TestCase { }); jobExecutor.run(jobConfiguration, jobExecution); assertEquals(2, list.size()); - checkRepository(BatchStatus.COMPLETED, ExitStatus.FINISHED.getExitCode()); + checkRepository(BatchStatus.COMPLETED, ExitStatus.FINISHED); } @@ -221,7 +221,7 @@ public class DefaultJobExecutorTests extends TestCase { assertEquals(exception, e.getCause()); } assertEquals(0, list.size()); - checkRepository(BatchStatus.STOPPED, ExitCodeExceptionClassifier.STEP_INTERRUPTED); + checkRepository(BatchStatus.STOPPED, new ExitStatus(false, ExitCodeExceptionClassifier.STEP_INTERRUPTED)); } public void testFailed() throws Exception { @@ -241,7 +241,7 @@ public class DefaultJobExecutorTests extends TestCase { assertEquals(exception, e); } assertEquals(0, list.size()); - checkRepository(BatchStatus.FAILED, ExitCodeExceptionClassifier.FATAL_EXCEPTION); + checkRepository(BatchStatus.FAILED, new ExitStatus(false, ExitCodeExceptionClassifier.FATAL_EXCEPTION)); } public void testStepShouldNotStart() throws Exception { @@ -260,15 +260,15 @@ public class DefaultJobExecutorTests extends TestCase { /* * Check JobRepository to ensure status is being saved. */ - private void checkRepository(BatchStatus status, String exitCode) { + private void checkRepository(BatchStatus status, ExitStatus exitStatus) { assertEquals(job, jobDao.findJobs(jobIdentifer).get(0)); // because map dao stores in memory, it can be checked directly assertEquals(status, job.getStatus()); JobExecution jobExecution = (JobExecution) jobDao.findJobExecutions(job).get(0); assertEquals(job.getId(), jobExecution.getJobId()); assertEquals(status, jobExecution.getStatus()); - if(exitCode != null){ - assertEquals(jobExecution.getExitCode(), exitCode); + if(exitStatus != null){ + assertEquals(jobExecution.getExitStatus().getExitCode(), exitStatus.getExitCode()); } } diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java index eb88ae2d0..22fc9b54e 100644 --- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java @@ -29,18 +29,20 @@ import org.springframework.batch.core.domain.JobInstance; import org.springframework.batch.core.repository.NoSuchBatchDomainObjectException; import org.springframework.batch.core.runtime.SimpleJobIdentifier; import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.jdbc.core.RowMapper; import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; import org.springframework.util.ClassUtils; /** * @author Dave Syer - * + * */ public abstract class AbstractJobDaoTests extends AbstractTransactionalDataSourceSpringContextTests { - private static final String GET_JOB_EXECUTION = "SELECT JOB_ID, START_TIME, END_TIME, STATUS, EXIT_CODE from " + private static final String GET_JOB_EXECUTION = "SELECT JOB_ID, START_TIME, END_TIME, STATUS, " + + "CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from " + "BATCH_JOB_EXECUTION where ID = ?"; protected JobDao jobDao; @@ -164,18 +166,18 @@ public abstract class AbstractJobDaoTests extends public void testUpdateJobExecution() { jobExecution.setStatus(BatchStatus.COMPLETED); - jobExecution.setExitCode("COMPLETED"); + jobExecution.setExitStatus(ExitStatus.FINISHED); jobExecution.setEndTime(new Timestamp(System.currentTimeMillis())); jobDao.update(jobExecution); List executions = retrieveJobExecution(jobExecution.getId()); assertEquals(executions.size(), 1); validateJobExecution(jobExecution, (JobExecution) executions.get(0)); - + } - - public void testSaveJobExecution(){ - + + public void testSaveJobExecution() { + List executions = retrieveJobExecution(jobExecution.getId()); assertEquals(executions.size(), 1); validateJobExecution(jobExecution, (JobExecution) executions.get(0)); @@ -240,15 +242,15 @@ public abstract class AbstractJobDaoTests extends assertEquals(job.getName(), ((Map) jobs.get(0)).get("JOB_NAME")); } - - private void validateJobExecution(JobExecution lhs, JobExecution rhs){ - - //equals operator only checks id + + private void validateJobExecution(JobExecution lhs, JobExecution rhs) { + + // equals operator only checks id assertEquals(lhs, rhs); assertEquals(lhs.getStartTime(), rhs.getStartTime()); assertEquals(lhs.getEndTime(), rhs.getEndTime()); assertEquals(lhs.getStatus(), rhs.getStatus()); - assertEquals(lhs.getExitCode(), rhs.getExitCode()); + assertEquals(lhs.getExitStatus(), rhs.getExitStatus()); } private List retrieveJobExecution(final Long id) { @@ -256,12 +258,14 @@ public abstract class AbstractJobDaoTests extends RowMapper rowMapper = new RowMapper() { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - JobExecution execution = new JobExecution(new JobInstance(jobRuntimeInformation, new Long(rs - .getLong(1)))); + JobExecution execution = new JobExecution(new JobInstance( + jobRuntimeInformation, new Long(rs.getLong(1)))); execution.setStartTime(rs.getTimestamp(2)); execution.setEndTime(rs.getTimestamp(3)); execution.setStatus(BatchStatus.getStatus(rs.getString(4))); - execution.setExitCode(rs.getString(5)); + // TODO: Add boolean for continuable to queries + execution.setExitStatus(new ExitStatus("Y".equals(rs + .getString(5)), rs.getString(6), rs.getString(7))); execution.setId(id); return execution; diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java index e14082ffa..7d3b8d3ff 100644 --- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java @@ -28,6 +28,7 @@ import org.springframework.batch.core.domain.StepInstance; import org.springframework.batch.core.executor.ExitCodeExceptionClassifier; import org.springframework.batch.core.runtime.JobIdentifier; import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.restart.GenericRestartData; import org.springframework.batch.restart.RestartData; import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; @@ -165,16 +166,14 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour statistics.setProperty("statistic.key1", "0"); statistics.setProperty("statistic.key2", "5"); execution.setStatistics(statistics); - execution.setExitCode(ExitCodeExceptionClassifier.FATAL_EXCEPTION); - execution.setExitDescription("java.lang.Exception"); + execution.setExitStatus(new ExitStatus(false, ExitCodeExceptionClassifier.FATAL_EXCEPTION, "java.lang.Exception")); stepDao.save(execution); List executions = stepDao.findStepExecutions(step2); assertEquals(1, executions.size()); StepExecution tempExecution = (StepExecution)executions.get(0); assertEquals(execution, tempExecution); assertEquals(execution.getStatistics(), tempExecution.getStatistics()); - assertEquals(tempExecution.getExitCode(), execution.getExitCode()); - assertEquals(tempExecution.getExitDescription(), execution.getExitDescription()); + assertEquals(execution.getExitStatus(), tempExecution.getExitStatus()); } public void testUpdateStepExecution(){ @@ -184,15 +183,13 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour stepExecution.setCommitCount(5); stepExecution.setTaskCount(5); stepExecution.setStatistics(new Properties()); - stepExecution.setExitCode(ExitCodeExceptionClassifier.FATAL_EXCEPTION); - stepExecution.setExitDescription("java.lang.Exception"); + stepExecution.setExitStatus(new ExitStatus(false, ExitCodeExceptionClassifier.FATAL_EXCEPTION, "java.lang.Exception")); stepDao.update(stepExecution); List executions = stepDao.findStepExecutions(step1); assertEquals(1, executions.size()); StepExecution tempExecution = (StepExecution)executions.get(0); assertEquals(stepExecution, tempExecution); - assertEquals(tempExecution.getExitCode(), stepExecution.getExitCode()); - assertEquals(tempExecution.getExitDescription(), stepExecution.getExitDescription()); + assertEquals(stepExecution.getExitStatus(), tempExecution.getExitStatus()); } public void testUpdateStepExecutionWithNullId(){ diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/ExitStatusUserTypeTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/ExitStatusUserTypeTests.java new file mode 100644 index 000000000..d675a78c1 --- /dev/null +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/ExitStatusUserTypeTests.java @@ -0,0 +1,51 @@ +package org.springframework.batch.execution.repository.dao; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Types; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.repeat.ExitStatus; + +public class ExitStatusUserTypeTests extends TestCase { + + ExitStatusUserType type = new ExitStatusUserType(); + + public void testReturnedClass() { + assertEquals(ExitStatus.class, type.returnedClass()); + } + + public void testSqlTypes() { + int[] types = type.sqlTypes(); + assertEquals(3, types.length); + assertEquals(Types.CHAR, types[0]); + } + + public void testNullSafeGet() throws Exception { + String[] names = new String[] {"a", "b", "c"}; + MockControl control = MockControl.createControl(ResultSet.class); + ResultSet rs = (ResultSet) control.getMock(); + control.expectAndReturn(rs.getString(names[0]), "Y"); + control.expectAndReturn(rs.getString(names[1]), "foo"); + control.expectAndReturn(rs.getString(names[2]), "bar"); + control.replay(); + Object result = type.nullSafeGet(rs, names, null); + assertNotNull(result); + assertTrue(result instanceof ExitStatus); + control.verify(); + } + + public void testNullSafeSet() throws Exception { + MockControl control = MockControl.createControl(PreparedStatement.class); + PreparedStatement st = (PreparedStatement) control.getMock(); + st.setString(2, "Y"); + st.setString(3, ExitStatus.CONTINUABLE.getExitCode()); + st.setString(4, ExitStatus.CONTINUABLE.getExitDescription()); + control.replay(); + type.nullSafeSet(st, ExitStatus.CONTINUABLE, 2); + control.verify(); + } + +} diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/ImmutableValueUserTypeTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/ImmutableValueUserTypeTests.java new file mode 100644 index 000000000..e84701ff9 --- /dev/null +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/ImmutableValueUserTypeTests.java @@ -0,0 +1,61 @@ +package org.springframework.batch.execution.repository.dao; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.hibernate.HibernateException; + +import junit.framework.TestCase; + +public class ImmutableValueUserTypeTests extends TestCase { + + ImmutableValueUserType type = new ImmutableValueUserType() { + public Object nullSafeGet(ResultSet rs, String[] names, Object owner) + throws HibernateException, SQLException { + return null; + } + public void nullSafeSet(PreparedStatement st, Object value, int index) + throws HibernateException, SQLException { + } + public Class returnedClass() { + return null; + } + public int[] sqlTypes() { + return null; + } + }; + + public void testAssemble() { + assertEquals("foo", type.assemble("foo", null)); + } + + public void testDeepCopy() { + assertEquals("foo", type.deepCopy("foo")); + } + + public void testDisassemble() { + assertEquals("foo", type.disassemble("foo")); + } + + public void testEqualsWithEqualObjects() { + assertTrue(type.equals("foo", "foo")); + } + + public void testEqualsWithUnEqualObjects() { + assertFalse(type.equals("foo", "bar")); + } + + public void testHashCodeObject() { + assertEquals("foo".hashCode(), type.hashCode("foo")); + } + + public void testIsMutable() { + assertFalse(type.isMutable()); + } + + public void testReplace() { + assertEquals("foo",type.replace("foo", "bar", null)); + } + +} diff --git a/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java b/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java index 127ad6083..c6a561e72 100644 --- a/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/step/simple/DefaultStepExecutorTests.java @@ -71,7 +71,9 @@ public class DefaultStepExecutorTests extends TestCase { return module; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see junit.framework.TestCase#setUp() */ protected void setUp() throws Exception { @@ -79,7 +81,8 @@ public class DefaultStepExecutorTests extends TestCase { stepExecutor = new DefaultStepExecutor(); stepExecutor.setRepository(new JobRepositorySupport()); stepConfiguration = new SimpleStepConfiguration(); - stepConfiguration.setTasklet(getTasklet(new String[] {"foo", "bar", "spam"})); + stepConfiguration.setTasklet(getTasklet(new String[] { "foo", "bar", + "spam" })); // Only process one chunk: RepeatTemplate template = new RepeatTemplate(); template.setCompletionPolicy(new SimpleCompletionPolicy(1)); @@ -94,8 +97,10 @@ public class DefaultStepExecutorTests extends TestCase { StepInstance step = new StepInstance(new Long(9)); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - JobExecution jobExecutionContext = new JobExecution(new JobInstance(jobIdentifier, new Long(3))); - StepExecution stepExecution = new StepExecution(step, jobExecutionContext); + JobExecution jobExecutionContext = new JobExecution(new JobInstance( + jobIdentifier, new Long(3))); + StepExecution stepExecution = new StepExecution(step, + jobExecutionContext); stepExecutor.process(stepConfiguration, stepExecution); assertEquals(1, processed.size()); @@ -111,7 +116,8 @@ public class DefaultStepExecutorTests extends TestCase { StepInstance step = new StepInstance(new Long(1)); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - JobExecution jobExecution = new JobExecution(new JobInstance(jobIdentifier, new Long(1))); + JobExecution jobExecution = new JobExecution(new JobInstance( + jobIdentifier, new Long(1))); step.setStepExecution(new StepExecution(step, jobExecution)); StepExecution stepExecution = new StepExecution(step, jobExecution); @@ -130,16 +136,19 @@ public class DefaultStepExecutorTests extends TestCase { final StepInstance step = new StepInstance(new Long(1)); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - final JobExecution jobExecution = new JobExecution(new JobInstance(jobIdentifier, new Long(3))); - step.setStepExecution(new StepExecution(step,jobExecution)); - final StepExecution stepExecution = new StepExecution(step, jobExecution); + final JobExecution jobExecution = new JobExecution(new JobInstance( + jobIdentifier, new Long(3))); + step.setStepExecution(new StepExecution(step, jobExecution)); + final StepExecution stepExecution = new StepExecution(step, + jobExecution); stepConfiguration.setTasklet(new Tasklet() { public ExitStatus execute() throws Exception { assertEquals(step, stepExecution.getStep()); assertEquals(1, jobExecution.getChunkContexts().size()); assertEquals(1, jobExecution.getStepContexts().size()); - assertNotNull(StepSynchronizationManager.getContext().getJobIdentifier()); + assertNotNull(StepSynchronizationManager.getContext() + .getJobIdentifier()); processed.add("foo"); return ExitStatus.CONTINUABLE; } @@ -152,27 +161,30 @@ public class DefaultStepExecutorTests extends TestCase { public void testRepository() throws Exception { - SimpleJobRepository repository = new SimpleJobRepository(new MapJobDao(), new MapStepDao()); + SimpleJobRepository repository = new SimpleJobRepository( + new MapJobDao(), new MapStepDao()); stepExecutor.setRepository(repository); StepInstance step = new StepInstance(new Long(1)); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - JobExecution jobExecutionContext = new JobExecution(new JobInstance(jobIdentifier, new Long(3))); - StepExecution stepExecution = new StepExecution(step, jobExecutionContext); + JobExecution jobExecutionContext = new JobExecution(new JobInstance( + jobIdentifier, new Long(3))); + StepExecution stepExecution = new StepExecution(step, + jobExecutionContext); stepExecutor.process(stepConfiguration, stepExecution); assertEquals(1, processed.size()); } - public void testIncrementRollbackCount(){ + public void testIncrementRollbackCount() { - Tasklet tasklet = new Tasklet(){ + Tasklet tasklet = new Tasklet() { public ExitStatus execute() throws Exception { int counter = 0; counter++; - if(counter == 1){ + if (counter == 1) { throw new Exception(); } @@ -184,27 +196,29 @@ public class DefaultStepExecutorTests extends TestCase { StepInstance step = new StepInstance(new Long(1)); stepConfiguration.setTasklet(tasklet); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - JobExecution jobExecutionContext = new JobExecution(new JobInstance(jobIdentifier, new Long(3))); - StepExecution stepExecution = new StepExecution(step, jobExecutionContext); + JobExecution jobExecutionContext = new JobExecution(new JobInstance( + jobIdentifier, new Long(3))); + StepExecution stepExecution = new StepExecution(step, + jobExecutionContext); - try{ + try { stepExecutor.process(stepConfiguration, stepExecution); - } - catch(Exception ex){ - assertEquals(step.getStepExecution().getRollbackCount(), new Integer(1)); + } catch (Exception ex) { + assertEquals(step.getStepExecution().getRollbackCount(), + new Integer(1)); } } - public void testExitCodeDefaultClassification(){ + public void testExitCodeDefaultClassification() { - Tasklet tasklet = new Tasklet(){ + Tasklet tasklet = new Tasklet() { public ExitStatus execute() throws Exception { int counter = 0; counter++; - if(counter == 1){ + if (counter == 1) { throw new RuntimeException(); } @@ -216,35 +230,39 @@ public class DefaultStepExecutorTests extends TestCase { StepInstance step = new StepInstance(new Long(1)); stepConfiguration.setTasklet(tasklet); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - JobExecution jobExecutionContext = new JobExecution(new JobInstance(jobIdentifier, new Long(3))); - StepExecution stepExecution = new StepExecution(step, jobExecutionContext); + JobExecution jobExecutionContext = new JobExecution(new JobInstance( + jobIdentifier, new Long(3))); + StepExecution stepExecution = new StepExecution(step, + jobExecutionContext); - try{ + try { stepExecutor.process(stepConfiguration, stepExecution); - } - catch(Exception ex){ - assertEquals(step.getStepExecution().getExitCode(), ExitCodeExceptionClassifier.FATAL_EXCEPTION); - assertEquals(step.getStepExecution().getExitDescription(), "java.lang.RuntimeException"); + } catch (Exception ex) { + assertEquals(step.getStepExecution().getExitStatus(), + new ExitStatus(false, + ExitCodeExceptionClassifier.FATAL_EXCEPTION, + "java.lang.RuntimeException")); } } - /* * make sure a job that has never been executed before, but does have * saveRestartData = true, doesn't have restoreFrom called on it. */ - public void testNonRestartedJob(){ + public void testNonRestartedJob() { StepInstance step = new StepInstance(new Long(1)); MockRestartableTasklet tasklet = new MockRestartableTasklet(); stepConfiguration.setTasklet(tasklet); stepConfiguration.setSaveRestartData(true); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - JobExecution jobExecutionContext = new JobExecution(new JobInstance(jobIdentifier, new Long(3))); - StepExecution stepExecution = new StepExecution(step, jobExecutionContext); + JobExecution jobExecutionContext = new JobExecution(new JobInstance( + jobIdentifier, new Long(3))); + StepExecution stepExecution = new StepExecution(step, + jobExecutionContext); - try{ + try { stepExecutor.process(stepConfiguration, stepExecution); - }catch(Throwable t){ + } catch (Throwable t) { fail(); } @@ -253,22 +271,24 @@ public class DefaultStepExecutorTests extends TestCase { } /* - * make sure a job that has been executed before, and is therefore being restarted, - * is restored. + * make sure a job that has been executed before, and is therefore being + * restarted, is restored. */ - public void testRestartedJob(){ + public void testRestartedJob() { StepInstance step = new StepInstance(new Long(1)); step.setStepExecutionCount(1); MockRestartableTasklet tasklet = new MockRestartableTasklet(); stepConfiguration.setTasklet(tasklet); stepConfiguration.setSaveRestartData(true); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - JobExecution jobExecutionContext = new JobExecution(new JobInstance(jobIdentifier, new Long(3))); - StepExecution stepExecution = new StepExecution(step, jobExecutionContext); + JobExecution jobExecutionContext = new JobExecution(new JobInstance( + jobIdentifier, new Long(3))); + StepExecution stepExecution = new StepExecution(step, + jobExecutionContext); - try{ + try { stepExecutor.process(stepConfiguration, stepExecution); - }catch(Throwable t){ + } catch (Throwable t) { fail(); } @@ -277,22 +297,24 @@ public class DefaultStepExecutorTests extends TestCase { } /* - * Test that a job that is being restarted, but has saveRestartData - * set to false, doesn't have restore or getRestartData called on it. + * Test that a job that is being restarted, but has saveRestartData set to + * false, doesn't have restore or getRestartData called on it. */ - public void testNoSaveRestartDataRestartableJob(){ + public void testNoSaveRestartDataRestartableJob() { StepInstance step = new StepInstance(new Long(1)); step.setStepExecutionCount(1); MockRestartableTasklet tasklet = new MockRestartableTasklet(); stepConfiguration.setTasklet(tasklet); stepConfiguration.setSaveRestartData(false); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - JobExecution jobExecutionContext = new JobExecution(new JobInstance(jobIdentifier, new Long(3))); - StepExecution stepExecution = new StepExecution(step, jobExecutionContext); + JobExecution jobExecutionContext = new JobExecution(new JobInstance( + jobIdentifier, new Long(3))); + StepExecution stepExecution = new StepExecution(step, + jobExecutionContext); - try{ + try { stepExecutor.process(stepConfiguration, stepExecution); - }catch(Throwable t){ + } catch (Throwable t) { fail(); } @@ -301,30 +323,31 @@ public class DefaultStepExecutorTests extends TestCase { } /* - * Even though the job is restarted, and saveRestartData is true, - * nothing will be restored because the Tasklet does not implement - * Restartable. + * Even though the job is restarted, and saveRestartData is true, nothing + * will be restored because the Tasklet does not implement Restartable. */ - public void testRestartJobOnNonRestartableTasklet(){ + public void testRestartJobOnNonRestartableTasklet() { StepInstance step = new StepInstance(new Long(1)); step.setStepExecutionCount(1); - stepConfiguration.setTasklet(new Tasklet(){ + stepConfiguration.setTasklet(new Tasklet() { public ExitStatus execute() throws Exception { - return ExitStatus.FINISHED; - }}); + return ExitStatus.FINISHED; + } + }); stepConfiguration.setSaveRestartData(true); SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("FOO"); - JobExecution jobExecution = new JobExecution(new JobInstance(jobIdentifier, new Long(3))); + JobExecution jobExecution = new JobExecution(new JobInstance( + jobIdentifier, new Long(3))); StepExecution stepExecution = new StepExecution(step, jobExecution); - try{ + try { stepExecutor.process(stepConfiguration, stepExecution); - }catch(Throwable t){ + } catch (Throwable t) { fail(); } } - private class MockRestartableTasklet implements Tasklet, Restartable{ + private class MockRestartableTasklet implements Tasklet, Restartable { private boolean getRestartDataCalled = false; private boolean restoreFromCalled = false; @@ -352,49 +375,42 @@ public class DefaultStepExecutorTests extends TestCase { } /* - * StepExecutor will never pass StepInterruptedException to the exceptionClassifier. - * This may or may not stay the same, so the test will remain commented out - * for reference purposes. + * StepExecutor will never pass StepInterruptedException to the + * exceptionClassifier. This may or may not stay the same, so the test will + * remain commented out for reference purposes. + */ + /* + * public void testExitCodeInterruptedClassification(){ + * + * StepInterruptionPolicy interruptionPolicy = new StepInterruptionPolicy(){ + * + * public void checkInterrupted(RepeatContext context) throws + * StepInterruptedException { throw new StepInterruptedException(""); } + * }; + * + * stepExecutor.setInterruptionPolicy(interruptionPolicy); + * + * Tasklet tasklet = new Tasklet(){ + * + * public ExitStatus execute() throws Exception { int counter = 0; + * counter++; + * + * if(counter == 1){ throw new StepInterruptedException(""); } + * + * return ExitStatus.CONTINUABLE; } + * }; + * + * StepInstance step = new StepInstance(new Long(1)); + * stepConfiguration.setTasklet(tasklet); JobExecutionContext + * jobExecutionContext = new JobExecutionContext(new + * SimpleJobIdentifier("FOO"), new JobInstance(new Long(3))); StepExecution + * stepExecution = new StepExecution(step, jobExecutionContext); + * + * try{ stepExecutor.process(stepConfiguration, stepExecution); } + * catch(Exception ex){ + * assertEquals(ExitCodeExceptionClassifier.STEP_INTERRUPTED, + * step.getStepExecution().getExitCode() ); + * assertEquals(step.getStepExecution().getExitDescription(), + * "java.lang.RuntimeException"); } } */ -/* public void testExitCodeInterruptedClassification(){ - - StepInterruptionPolicy interruptionPolicy = new StepInterruptionPolicy(){ - - public void checkInterrupted(RepeatContext context) - throws StepInterruptedException { - throw new StepInterruptedException(""); - } - - }; - - stepExecutor.setInterruptionPolicy(interruptionPolicy); - - Tasklet tasklet = new Tasklet(){ - - public ExitStatus execute() throws Exception { - int counter = 0; - counter++; - - if(counter == 1){ - throw new StepInterruptedException(""); - } - - return ExitStatus.CONTINUABLE; - } - - }; - - StepInstance step = new StepInstance(new Long(1)); - stepConfiguration.setTasklet(tasklet); - JobExecutionContext jobExecutionContext = new JobExecutionContext(new SimpleJobIdentifier("FOO"), new JobInstance(new Long(3))); - StepExecution stepExecution = new StepExecution(step, jobExecutionContext); - - try{ - stepExecutor.process(stepConfiguration, stepExecution); - } - catch(Exception ex){ - assertEquals(ExitCodeExceptionClassifier.STEP_INTERRUPTED, step.getStepExecution().getExitCode() ); - assertEquals(step.getStepExecution().getExitDescription(), "java.lang.RuntimeException"); - } - }*/ } diff --git a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/init.sql b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/init.sql index eb3630793..90d3debc4 100644 --- a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/init.sql +++ b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/init.sql @@ -15,7 +15,9 @@ CREATE TABLE BATCH_JOB_EXECUTION ( START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP , STATUS VARCHAR(10), - EXIT_CODE VARCHAR(250)); + CONTINUABLE CHAR(1), + EXIT_CODE VARCHAR(20), + EXIT_MESSAGE VARCHAR(250)); CREATE TABLE BATCH_STEP ( ID BIGINT IDENTITY PRIMARY KEY , @@ -36,7 +38,8 @@ CREATE TABLE BATCH_STEP_EXECUTION ( COMMIT_COUNT BIGINT , TASK_COUNT BIGINT , TASK_STATISTICS VARCHAR(250), - EXIT_CODE VARCHAR(250), + CONTINUABLE CHAR(1), + EXIT_CODE VARCHAR(20), EXIT_MESSAGE VARCHAR(250)); CREATE TABLE BATCH_STEP_EXECUTION_SEQ ( diff --git a/infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java b/infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java index 94e805066..c30f89511 100644 --- a/infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java +++ b/infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java @@ -32,20 +32,25 @@ public class ExitStatus implements Serializable { */ public static final ExitStatus RUNNING = new ExitStatus(true, "RUNNING"); + /** + * Convenient constant value representing unknown state - assumed continuable. + */ + public static final ExitStatus UNKNOWN = new ExitStatus(true, "UNKNOWN"); + /** * Convenient constant value representing unfinished processing. */ - public static ExitStatus CONTINUABLE = new ExitStatus(true); + public static final ExitStatus CONTINUABLE = new ExitStatus(true, "CONTINUABLE"); /** * Convenient constant value representing finished processing. */ - public static ExitStatus FINISHED = new ExitStatus(false, "COMPLETED"); + public static final ExitStatus FINISHED = new ExitStatus(false, "COMPLETED"); /** * Convenient constant value representing finished processing with an error. */ - public static ExitStatus FAILED = new ExitStatus(false, "FAILED"); + public static final ExitStatus FAILED = new ExitStatus(false, "FAILED"); private final boolean continuable; @@ -121,6 +126,18 @@ public class ExitStatus implements Serializable { return "continuable=" + continuable + ";exitCode=" + exitCode + ";exitDescription=" + exitDescription; } + + /** + * Compare the fields one by one. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (obj==null) { + return false; + } + return toString().equals(obj.toString()); + } /** * Add an exit code to an existing {@link ExitStatus}. diff --git a/infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java b/infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java index c527fba6f..d2819db50 100644 --- a/infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java +++ b/infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java @@ -40,7 +40,7 @@ public class ExitStatusTests extends TestCase { public void testExitStatusConstantsContinuable() { ExitStatus status = ExitStatus.CONTINUABLE; assertTrue(status.isContinuable()); - assertEquals("", status.getExitCode()); + assertEquals("CONTINUABLE", status.getExitCode()); } /** @@ -51,6 +51,24 @@ public class ExitStatusTests extends TestCase { assertFalse(status.isContinuable()); assertEquals("COMPLETED", status.getExitCode()); } + + /** + * Test equality of exit statuses. + * + * @throws Exception + */ + public void testEqualsWithSameProperties() throws Exception { + assertEquals(ExitStatus.CONTINUABLE, new ExitStatus(true, "CONTINUABLE")); + } + + /** + * Test equality of exit statuses. + * + * @throws Exception + */ + public void testEqualsWithNull() throws Exception { + assertFalse(ExitStatus.CONTINUABLE.equals(null)); + } /** * Test method for {@link org.springframework.batch.repeat.ExitStatus#and(boolean)}.