OPEN - issue BATCH-90: StepExecution and StepExecutionContext are parallel domains, and StepExecution is by comparison anaemic

http://opensource.atlassian.com/projects/spring/browse/BATCH-90

Add ExitStatus to *Execution entities
This commit is contained in:
dsyer
2007-09-30 21:16:44 +00:00
parent 484961f5ab
commit 9d44d8f455
28 changed files with 541 additions and 489 deletions

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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 {

View File

@@ -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());
}
/**

View File

@@ -47,3 +47,4 @@ incrementer
hoc
unbind
tasklet
bespoke

View File

@@ -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);
}

View File

@@ -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 };
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
};

View File

@@ -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);

View File

@@ -16,7 +16,11 @@
<property name="startTime" column="START_TIME" />
<property name="endTime" column="END_TIME" />
<property name="status" type="org.springframework.batch.execution.repository.dao.BatchStatusUserType" column="STATUS" />
<property name="exitCode" column="EXIT_CODE" />
<property name="exitStatus" type="org.springframework.batch.execution.repository.dao.ExitStatusUserType">
<column name="CONTINUABLE"/>
<column name="EXIT_CODE"/>
<column name="EXIT_MESSAGE"/>
</property>
</class>
</hibernate-mapping>

View File

@@ -20,7 +20,11 @@
<property name="commitCount" column="COMMIT_COUNT" />
<property name="taskCount" column="TASK_COUNT" />
<property name="statistics" type="org.springframework.batch.execution.repository.dao.PropertiesUserType" column="TASK_STATISTICS" />
<property name="exitCode" column="EXIT_CODE" />
<property name="exitStatus" type="org.springframework.batch.execution.repository.dao.ExitStatusUserType">
<column name="CONTINUABLE"/>
<column name="EXIT_CODE"/>
<column name="EXIT_MESSAGE"/>
</property>
</class>
</hibernate-mapping>

View File

@@ -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;

View File

@@ -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;

View File

@@ -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
);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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" )

View File

@@ -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());
}
}

View File

@@ -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;

View File

@@ -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(){

View File

@@ -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();
}
}

View File

@@ -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));
}
}

View File

@@ -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");
}
}*/
}

View File

@@ -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 (

View File

@@ -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}.

View File

@@ -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)}.