diff --git a/pom.xml b/pom.xml index 6df3752ff..2ce1e77d9 100644 --- a/pom.xml +++ b/pom.xml @@ -499,8 +499,12 @@ com.thoughtworks.xstream xstream - 1.2.1 - true + 1.3 + + + org.codehaus.jettison + jettison + 1.0.1 stax diff --git a/spring-batch-core/pom.xml b/spring-batch-core/pom.xml index b0be41527..9b4e935bd 100644 --- a/spring-batch-core/pom.xml +++ b/spring-batch-core/pom.xml @@ -74,6 +74,14 @@ cglib-nodep test + + com.thoughtworks.xstream + xstream + + + org.codehaus.jettison + jettison + org.springframework diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java index 92b0fa0f9..ae3551cbc 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java @@ -1,22 +1,22 @@ package org.springframework.batch.core.repository.dao; -import java.io.Serializable; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.PreparedStatement; +import java.sql.Types; import java.util.Map.Entry; +import java.util.HashMap; +import java.util.Map; +import java.util.List; -import org.apache.commons.lang.SerializationUtils; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.UnexpectedJobExecutionException; +import org.springframework.batch.core.repository.support.ExecutionContextStringSerializer; +import org.springframework.batch.core.repository.support.XStreamExecutionContextStringSerializer; import org.springframework.batch.item.ExecutionContext; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.PreparedStatementCallback; -import org.springframework.jdbc.core.RowCallbackHandler; -import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback; +import org.springframework.jdbc.core.simple.ParameterizedRowMapper; +import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.support.lob.DefaultLobHandler; -import org.springframework.jdbc.support.lob.LobCreator; import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.util.Assert; @@ -28,35 +28,62 @@ import org.springframework.util.Assert; * * @author Lucas Ward * @author Robert Kasanicky + * @author Thomas Risberg */ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implements ExecutionContextDao { - private static final String FIND_EXECUTION_CONTEXT = "SELECT TYPE_CD, KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL " - + "from %PREFIX%EXECUTION_CONTEXT where EXECUTION_ID = ? and DISCRIMINATOR = ?"; + private static final String COUNT_JOB_EXECUTION_CONTEXT = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION_CONTEXT " + + "WHERE JOB_EXECUTION_ID = ?"; - private static final String INSERT_STEP_EXECUTION_CONTEXT = "INSERT into %PREFIX%EXECUTION_CONTEXT(EXECUTION_ID, DISCRIMINATOR, TYPE_CD," - + " KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL) values(?,?,?,?,?,?,?,?)"; + private static final String FIND_JOB_EXECUTION_CONTEXT = "SELECT SHORT_CONTEXT, SERIALIZED_CONTEXT " + + "FROM %PREFIX%JOB_EXECUTION_CONTEXT WHERE JOB_EXECUTION_ID = ?"; - private static final String UPDATE_STEP_EXECUTION_CONTEXT = "UPDATE %PREFIX%EXECUTION_CONTEXT set " - + "TYPE_CD = ?, STRING_VAL = ?, DOUBLE_VAL = ?, LONG_VAL = ?, OBJECT_VAL = ? where EXECUTION_ID = ? and KEY_NAME = ?"; + private static final String INSERT_JOB_EXECUTION_CONTEXT = "INSERT INTO %PREFIX%JOB_EXECUTION_CONTEXT " + + "(JOB_EXECUTION_ID, SHORT_CONTEXT, SERIALIZED_CONTEXT) " + + "VALUES(?, ?, ?)"; + + private static final String UPDATE_JOB_EXECUTION_CONTEXT = "UPDATE %PREFIX%JOB_EXECUTION_CONTEXT " + + "SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? " + + "WHERE JOB_EXECUTION_ID = ?"; + + private static final String COUNT_STEP_EXECUTION_CONTEXT = "SELECT COUNT(*) FROM %PREFIX%STEP_EXECUTION_CONTEXT " + + "WHERE STEP_EXECUTION_ID = ?"; + + private static final String FIND_STEP_EXECUTION_CONTEXT = "SELECT SHORT_CONTEXT, SERIALIZED_CONTEXT " + + "FROM %PREFIX%STEP_EXECUTION_CONTEXT WHERE STEP_EXECUTION_ID = ?"; + + + private static final String INSERT_STEP_EXECUTION_CONTEXT = "INSERT INTO %PREFIX%STEP_EXECUTION_CONTEXT " + + "(STEP_EXECUTION_ID, SHORT_CONTEXT, SERIALIZED_CONTEXT) " + + "VALUES(?, ?, ?)"; + + private static final String UPDATE_STEP_EXECUTION_CONTEXT = "UPDATE %PREFIX%STEP_EXECUTION_CONTEXT " + + "SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? " + + "WHERE STEP_EXECUTION_ID = ?"; + + private static final int MAX_VARCHAR_LENGTH = 2500; private LobHandler lobHandler = new DefaultLobHandler(); + private ExecutionContextStringSerializer serializer; + /** * @param jobExecution * @return execution context associated with the given jobExecution. */ public ExecutionContext getExecutionContext(JobExecution jobExecution) { - final Long executionId = jobExecution.getId(); + Long executionId = jobExecution.getId(); Assert.notNull(executionId, "ExecutionId must not be null."); - final ExecutionContext executionContext = new ExecutionContext(); - - getJdbcTemplate().getJdbcOperations().query(getQuery(FIND_EXECUTION_CONTEXT), - new Object[] { executionId, Discriminator.JOB.toString() }, - new ExecutionContextRowCallbackHandler(executionContext)); - - return executionContext; + List results = getJdbcTemplate().query(getQuery(FIND_JOB_EXECUTION_CONTEXT), + new ExecutionContextRowMapper(), + executionId); + if (results.size() > 0) { + return results.get(0); + } + else { + return new ExecutionContext(); + } } /** @@ -64,16 +91,18 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem * @return execution context associated with the given stepExecution. */ public ExecutionContext getExecutionContext(StepExecution stepExecution) { - final Long executionId = stepExecution.getId(); + Long executionId = stepExecution.getId(); Assert.notNull(executionId, "ExecutionId must not be null."); - final ExecutionContext executionContext = new ExecutionContext(); - - getJdbcTemplate().getJdbcOperations().query(getQuery(FIND_EXECUTION_CONTEXT), - new Object[] { executionId, Discriminator.STEP.toString() }, - new ExecutionContextRowCallbackHandler(executionContext)); - - return executionContext; + List results = getJdbcTemplate().query(getQuery(FIND_STEP_EXECUTION_CONTEXT), + new ExecutionContextRowMapper(), + executionId); + if (results.size() > 0) { + return results.get(0); + } + else { + return new ExecutionContext(); + } } /** @@ -87,7 +116,9 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem Assert.notNull(executionId, "ExecutionId must not be null."); Assert.notNull(executionContext, "The ExecutionContext must not be null."); - saveOrUpdateExecutionContext(executionContext, executionId, Discriminator.JOB); + String serializedContext = serializeContext(executionContext); + + persistSerializedContext(executionId, serializedContext, true); } /** @@ -102,202 +133,93 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem Assert.notNull(executionId, "ExecutionId must not be null."); Assert.notNull(executionContext, "The ExecutionContext must not be null."); - saveOrUpdateExecutionContext(executionContext, executionId, Discriminator.STEP); - } + String serializedContext = serializeContext(executionContext); - /** - * Resolves attribute's class to corresponding {@link AttributeType} and - * persists or updates the attribute. - */ - private void saveOrUpdateExecutionContext(ExecutionContext ctx, Long executionId, Discriminator discriminator) { - - for (Entry entry : ctx.entrySet()) { - - final String key = entry.getKey().toString(); - final Object value = entry.getValue(); - - if (value instanceof String) { - updateExecutionAttribute(executionId, discriminator, key, value, AttributeType.STRING); - } - else if (value instanceof Double) { - updateExecutionAttribute(executionId, discriminator, key, value, AttributeType.DOUBLE); - } - else if (value instanceof Long) { - updateExecutionAttribute(executionId, discriminator, key, value, AttributeType.LONG); - } - else { - updateExecutionAttribute(executionId, discriminator, key, value, AttributeType.OBJECT); - } - } - } - - /** - * Creates {@link PreparedStatement} from the provided arguments and tries - * to update the attribute - if the attribute does not exist in the database - * yet it is inserted. - */ - private void updateExecutionAttribute(final Long executionId, final Discriminator discriminator, final String key, - final Object value, final AttributeType type) { - - PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) { - - protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, - DataAccessException { - - ps.setLong(6, executionId.longValue()); - ps.setString(7, key); - if (type == AttributeType.STRING) { - ps.setString(1, AttributeType.STRING.toString()); - ps.setString(2, value.toString()); - ps.setDouble(3, 0.0); - ps.setLong(4, 0); - lobCreator.setBlobAsBytes(ps, 5, null); - } - else if (type == AttributeType.DOUBLE) { - ps.setString(1, AttributeType.DOUBLE.toString()); - ps.setString(2, null); - ps.setDouble(3, ((Double) value).doubleValue()); - ps.setLong(4, 0); - lobCreator.setBlobAsBytes(ps, 5, null); - } - else if (type == AttributeType.LONG) { - ps.setString(1, AttributeType.LONG.toString()); - ps.setString(2, null); - ps.setDouble(3, 0.0); - ps.setLong(4, ((Long) value).longValue()); - lobCreator.setBlobAsBytes(ps, 5, null); - } - else { - ps.setString(1, AttributeType.OBJECT.toString()); - ps.setString(2, null); - ps.setDouble(3, 0.0); - ps.setLong(4, 0); - lobCreator.setBlobAsBytes(ps, 5, SerializationUtils.serialize((Serializable) value)); - } - } - }; - - // LobCreating callbacks always return the affect row count for SQL DML - // statements, if less than 1 row - // is affected, then this row is new and should be inserted. - Integer affectedRows = (Integer) getJdbcTemplate().getJdbcOperations().execute( - getQuery(UPDATE_STEP_EXECUTION_CONTEXT), callback); - if (affectedRows.intValue() < 1) { - insertExecutionAttribute(executionId, discriminator, key, value, type); - } - } - - /** - * Creates {@link PreparedStatement} from provided arguments and inserts new - * row for the attribute. - */ - private void insertExecutionAttribute(final Long executionId, final Discriminator discriminator, final String key, - final Object value, final AttributeType type) { - PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) { - - protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, - DataAccessException { - - ps.setLong(1, executionId.longValue()); - ps.setString(2, discriminator.toString()); - ps.setString(4, key); - if (type == AttributeType.STRING) { - ps.setString(3, AttributeType.STRING.toString()); - ps.setString(5, value.toString()); - ps.setDouble(6, 0.0); - ps.setLong(7, 0); - lobCreator.setBlobAsBytes(ps, 8, null); - } - else if (type == AttributeType.DOUBLE) { - ps.setString(3, AttributeType.DOUBLE.toString()); - ps.setString(5, null); - ps.setDouble(6, ((Double) value).doubleValue()); - ps.setLong(7, 0); - lobCreator.setBlobAsBytes(ps, 8, null); - } - else if (type == AttributeType.LONG) { - ps.setString(3, AttributeType.LONG.toString()); - ps.setString(5, null); - ps.setDouble(6, 0.0); - ps.setLong(7, ((Long) value).longValue()); - lobCreator.setBlobAsBytes(ps, 8, null); - } - else { - ps.setString(3, AttributeType.OBJECT.toString()); - ps.setString(5, null); - ps.setDouble(6, 0.0); - ps.setLong(7, 0); - lobCreator.setBlobAsBytes(ps, 8, SerializationUtils.serialize((Serializable) value)); - } - } - }; - getJdbcTemplate().getJdbcOperations().execute(getQuery(INSERT_STEP_EXECUTION_CONTEXT), callback); + persistSerializedContext(executionId, serializedContext, false); } public void setLobHandler(LobHandler lobHandler) { this.lobHandler = lobHandler; } - /** - * Attribute types supported by the {@link ExecutionContext}. - */ - private static enum AttributeType { - STRING, OBJECT, LONG, DOUBLE + @Override + public void afterPropertiesSet() throws Exception { + super.afterPropertiesSet(); + serializer = new XStreamExecutionContextStringSerializer(); + ((XStreamExecutionContextStringSerializer)serializer).afterPropertiesSet(); } - /** - * Discriminates whether the execution context belongs to job or step. - */ - private static enum Discriminator { + private void persistSerializedContext(final Long executionId, String serializedContext, boolean isJobExecutionContext) { + String countSql = isJobExecutionContext ? COUNT_JOB_EXECUTION_CONTEXT : COUNT_STEP_EXECUTION_CONTEXT; + String updateSql = isJobExecutionContext ? UPDATE_JOB_EXECUTION_CONTEXT : UPDATE_STEP_EXECUTION_CONTEXT; + String insertSql = isJobExecutionContext ? INSERT_JOB_EXECUTION_CONTEXT : INSERT_STEP_EXECUTION_CONTEXT; - STEP { - @Override - public String toString() { - return "S"; - } - }, + int count = getJdbcTemplate().queryForInt(getQuery(countSql), executionId); - JOB { - @Override - public String toString() { - return "J"; - } + final String shortContext; + final String longContext; + if (serializedContext.length() > MAX_VARCHAR_LENGTH) { + shortContext = serializedContext.substring(0, MAX_VARCHAR_LENGTH - 4) + " ..."; + longContext = serializedContext; + } + else { + shortContext = serializedContext; + longContext = null; + } + + + if (count > 0) { + getJdbcTemplate().getJdbcOperations().update(getQuery(updateSql), + new PreparedStatementSetter() { + public void setValues(PreparedStatement ps) throws SQLException { + ps.setString(1, shortContext); + if (longContext != null) { + lobHandler.getLobCreator().setClobAsString(ps, 2, longContext); + } + else { + ps.setNull(2, Types.CLOB); + } + ps.setLong(3, executionId); + } + }); + } + else { + getJdbcTemplate().getJdbcOperations().update(getQuery(insertSql), + new PreparedStatementSetter() { + public void setValues(PreparedStatement ps) throws SQLException { + ps.setLong(1, executionId); + ps.setString(2, shortContext); + if (longContext != null) { + lobHandler.getLobCreator().setClobAsString(ps, 3, longContext); + } + else { + ps.setNull(3, Types.CLOB); + } + } + }); } } - /** - * Reads attributes from {@link ResultSet} and puts them into - * {@link ExecutionContext}, resolving the attributes' types using the - * 'TYPE_CD' column. - */ - private static class ExecutionContextRowCallbackHandler implements RowCallbackHandler { - - private ExecutionContext executionContext; - - public ExecutionContextRowCallbackHandler(ExecutionContext ctx) { - executionContext = ctx; + private String serializeContext(ExecutionContext ctx) { + Map m = new HashMap(); + for (Entry me : ctx.entrySet()) { + m.put(me.getKey(), me.getValue()); } + return serializer.serialize(m); + } - public void processRow(ResultSet rs) throws SQLException { - - String typeCd = rs.getString("TYPE_CD"); - AttributeType type = AttributeType.valueOf(typeCd); - String key = rs.getString("KEY_NAME"); - if (type == AttributeType.STRING) { - executionContext.putString(key, rs.getString("STRING_VAL")); + private class ExecutionContextRowMapper implements ParameterizedRowMapper { + public ExecutionContext mapRow(ResultSet rs, int i) throws SQLException { + ExecutionContext executionContext = new ExecutionContext(); + String serializedContext = rs.getString("SERIALIZED_CONTEXT"); + if (serializedContext == null) { + serializedContext = rs.getString("SHORT_CONTEXT"); } - else if (type == AttributeType.LONG) { - executionContext.putLong(key, rs.getLong("LONG_VAL")); - } - else if (type == AttributeType.DOUBLE) { - executionContext.putDouble(key, rs.getDouble("DOUBLE_VAL")); - } - else if (type == AttributeType.OBJECT) { - executionContext.put(key, SerializationUtils.deserialize(rs.getBinaryStream("OBJECT_VAL"))); - } - else { - throw new UnexpectedJobExecutionException("Invalid type found: [" + typeCd + "]"); + Map map = serializer.deserialize(serializedContext); + for (Map.Entry entry : map.entrySet()) { + executionContext.put(entry.getKey(), entry.getValue()); } + return executionContext; } - }; + } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/ExecutionContextStringSerializer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/ExecutionContextStringSerializer.java new file mode 100644 index 000000000..79f255e7b --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/ExecutionContextStringSerializer.java @@ -0,0 +1,14 @@ +package org.springframework.batch.core.repository.support; + +import java.util.Map; + +/** + * @author trisberg + */ +public interface ExecutionContextStringSerializer { + + String serialize(Map context); + + Map deserialize(String context); + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/XStreamExecutionContextStringSerializer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/XStreamExecutionContextStringSerializer.java new file mode 100644 index 000000000..ff9450e6b --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/XStreamExecutionContextStringSerializer.java @@ -0,0 +1,54 @@ +package org.springframework.batch.core.repository.support; + +import com.thoughtworks.xstream.converters.reflection.ReflectionProvider; +import com.thoughtworks.xstream.io.HierarchicalStreamDriver; +import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; +import com.thoughtworks.xstream.XStream; + +import java.util.Map; + +import org.springframework.beans.factory.InitializingBean; + +/** + * @author trisberg + */ +public class XStreamExecutionContextStringSerializer implements ExecutionContextStringSerializer, InitializingBean { + + private ReflectionProvider reflectionProvider = null; + + private HierarchicalStreamDriver hierarchicalStreamDriver; + + private XStream xstream; + + public String serialize(Map context) { + return xstream.toXML(context); + } + + public Map deserialize(String context) { + return (Map) xstream.fromXML(context); + } + + public void setReflectionProvider(ReflectionProvider reflectionProvider) { + this.reflectionProvider = reflectionProvider; + } + + public void setHierarchicalStreamDriver(HierarchicalStreamDriver hierarchicalStreamDriver) { + this.hierarchicalStreamDriver = hierarchicalStreamDriver; + } + + public void afterPropertiesSet() throws Exception { + init(); + } + + public void init() throws Exception { + if (hierarchicalStreamDriver == null) { + this.hierarchicalStreamDriver = new JettisonMappedXmlDriver(); + } + if (reflectionProvider == null) { + xstream = new XStream(hierarchicalStreamDriver); + } + else { + xstream = new XStream(reflectionProvider, hierarchicalStreamDriver); + } + } +} diff --git a/spring-batch-core/src/main/resources/schema-db2.sql b/spring-batch-core/src/main/resources/schema-db2.sql index a4953f746..da6ca0db4 100644 --- a/spring-batch-core/src/main/resources/schema-db2.sql +++ b/spring-batch-core/src/main/resources/schema-db2.sql @@ -1,6 +1,7 @@ -- Autogenerated: do not edit this file -DROP TABLE BATCH_EXECUTION_CONTEXT ; +DROP TABLE BATCH_STEP_EXECUTION_CONTEXT ; +DROP TABLE BATCH_JOB_EXECUTION_CONTEXT ; DROP TABLE BATCH_STEP_EXECUTION ; DROP TABLE BATCH_JOB_EXECUTION ; DROP TABLE BATCH_JOB_PARAMS ; @@ -68,16 +69,20 @@ CREATE TABLE BATCH_STEP_EXECUTION ( references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; -CREATE TABLE BATCH_EXECUTION_CONTEXT ( - EXECUTION_ID BIGINT NOT NULL, - DISCRIMINATOR VARCHAR(1) NOT NULL, - TYPE_CD VARCHAR(6) NOT NULL, - KEY_NAME VARCHAR(1000) NOT NULL, - STRING_VAL VARCHAR(1000) , - DATE_VAL TIMESTAMP DEFAULT NULL, - LONG_VAL BIGINT , - DOUBLE_VAL DOUBLE PRECISION , - OBJECT_VAL BLOB +CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( + STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT CLOB , + constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) + references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) +) ; + +CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( + JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT CLOB , + constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) + references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; diff --git a/spring-batch-core/src/main/resources/schema-derby.sql b/spring-batch-core/src/main/resources/schema-derby.sql index 0ffa3c7b7..c297ebd54 100644 --- a/spring-batch-core/src/main/resources/schema-derby.sql +++ b/spring-batch-core/src/main/resources/schema-derby.sql @@ -1,6 +1,7 @@ -- Autogenerated: do not edit this file -DROP TABLE BATCH_EXECUTION_CONTEXT ; +DROP TABLE BATCH_STEP_EXECUTION_CONTEXT ; +DROP TABLE BATCH_JOB_EXECUTION_CONTEXT ; DROP TABLE BATCH_STEP_EXECUTION ; DROP TABLE BATCH_JOB_EXECUTION ; DROP TABLE BATCH_JOB_PARAMS ; @@ -68,16 +69,20 @@ CREATE TABLE BATCH_STEP_EXECUTION ( references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; -CREATE TABLE BATCH_EXECUTION_CONTEXT ( - EXECUTION_ID BIGINT NOT NULL, - DISCRIMINATOR VARCHAR(1) NOT NULL, - TYPE_CD VARCHAR(6) NOT NULL, - KEY_NAME VARCHAR(1000) NOT NULL, - STRING_VAL VARCHAR(1000) , - DATE_VAL TIMESTAMP DEFAULT NULL, - LONG_VAL BIGINT , - DOUBLE_VAL DOUBLE PRECISION , - OBJECT_VAL BLOB +CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( + STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT CLOB , + constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) + references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) +) ; + +CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( + JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT CLOB , + constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) + references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE TABLE BATCH_STEP_EXECUTION_SEQ (ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, DUMMY VARCHAR(1)); diff --git a/spring-batch-core/src/main/resources/schema-hsqldb.sql b/spring-batch-core/src/main/resources/schema-hsqldb.sql index 41a685272..99d9723ce 100644 --- a/spring-batch-core/src/main/resources/schema-hsqldb.sql +++ b/spring-batch-core/src/main/resources/schema-hsqldb.sql @@ -1,6 +1,7 @@ -- Autogenerated: do not edit this file -DROP TABLE BATCH_EXECUTION_CONTEXT IF EXISTS; +DROP TABLE BATCH_STEP_EXECUTION_CONTEXT IF EXISTS; +DROP TABLE BATCH_JOB_EXECUTION_CONTEXT IF EXISTS; DROP TABLE BATCH_STEP_EXECUTION IF EXISTS; DROP TABLE BATCH_JOB_EXECUTION IF EXISTS; DROP TABLE BATCH_JOB_PARAMS IF EXISTS; @@ -68,16 +69,20 @@ CREATE TABLE BATCH_STEP_EXECUTION ( references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; -CREATE TABLE BATCH_EXECUTION_CONTEXT ( - EXECUTION_ID BIGINT NOT NULL, - DISCRIMINATOR VARCHAR(1) NOT NULL, - TYPE_CD VARCHAR(6) NOT NULL, - KEY_NAME VARCHAR(1000) NOT NULL, - STRING_VAL VARCHAR(1000) , - DATE_VAL TIMESTAMP DEFAULT NULL, - LONG_VAL BIGINT , - DOUBLE_VAL DOUBLE PRECISION , - OBJECT_VAL LONGVARBINARY +CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( + STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT LONGVARCHAR , + constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) + references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) +) ; + +CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( + JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT LONGVARCHAR , + constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) + references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE TABLE BATCH_STEP_EXECUTION_SEQ ( diff --git a/spring-batch-core/src/main/resources/schema-mysql.sql b/spring-batch-core/src/main/resources/schema-mysql.sql index 494ac4985..3e9d3d5c5 100644 --- a/spring-batch-core/src/main/resources/schema-mysql.sql +++ b/spring-batch-core/src/main/resources/schema-mysql.sql @@ -1,6 +1,7 @@ -- Autogenerated: do not edit this file -DROP TABLE IF EXISTS BATCH_EXECUTION_CONTEXT ; +DROP TABLE IF EXISTS BATCH_STEP_EXECUTION_CONTEXT ; +DROP TABLE IF EXISTS BATCH_JOB_EXECUTION_CONTEXT ; DROP TABLE IF EXISTS BATCH_STEP_EXECUTION ; DROP TABLE IF EXISTS BATCH_JOB_EXECUTION ; DROP TABLE IF EXISTS BATCH_JOB_PARAMS ; @@ -15,7 +16,7 @@ CREATE TABLE BATCH_JOB_INSTANCE ( VERSION BIGINT , JOB_NAME VARCHAR(100) NOT NULL, JOB_KEY VARCHAR(2500) -) type=InnoDB; +) ENGINE=InnoDB; CREATE TABLE BATCH_JOB_EXECUTION ( JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY , @@ -31,7 +32,7 @@ CREATE TABLE BATCH_JOB_EXECUTION ( LAST_UPDATED DATETIME, constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID) references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID) -) type=InnoDB; +) ENGINE=InnoDB; CREATE TABLE BATCH_JOB_PARAMS ( JOB_INSTANCE_ID BIGINT NOT NULL , @@ -43,7 +44,7 @@ CREATE TABLE BATCH_JOB_PARAMS ( DOUBLE_VAL DOUBLE PRECISION , constraint JOB_INST_PARAMS_FK foreign key (JOB_INSTANCE_ID) references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID) -) type=InnoDB; +) ENGINE=InnoDB; CREATE TABLE BATCH_STEP_EXECUTION ( STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY , @@ -66,23 +67,27 @@ CREATE TABLE BATCH_STEP_EXECUTION ( LAST_UPDATED DATETIME, constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) -) type=InnoDB; +) ENGINE=InnoDB; -CREATE TABLE BATCH_EXECUTION_CONTEXT ( - EXECUTION_ID BIGINT NOT NULL, - DISCRIMINATOR VARCHAR(1) NOT NULL, - TYPE_CD VARCHAR(6) NOT NULL, - KEY_NAME VARCHAR(1000) NOT NULL, - STRING_VAL VARCHAR(1000) , - DATE_VAL DATETIME DEFAULT NULL, - LONG_VAL BIGINT , - DOUBLE_VAL DOUBLE PRECISION , - OBJECT_VAL BLOB -) type=InnoDB; +CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( + STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT TEXT , + constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) + references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) +) ENGINE=InnoDB; -CREATE TABLE BATCH_STEP_EXECUTION_SEQ (ID BIGINT NOT NULL) type=MYISAM; +CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( + JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT TEXT , + constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) + references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) +) ENGINE=InnoDB; + +CREATE TABLE BATCH_STEP_EXECUTION_SEQ (ID BIGINT NOT NULL) ENGINE=MYISAM; INSERT INTO BATCH_STEP_EXECUTION_SEQ values(0); -CREATE TABLE BATCH_JOB_EXECUTION_SEQ (ID BIGINT NOT NULL) type=MYISAM; +CREATE TABLE BATCH_JOB_EXECUTION_SEQ (ID BIGINT NOT NULL) ENGINE=MYISAM; INSERT INTO BATCH_JOB_EXECUTION_SEQ values(0); -CREATE TABLE BATCH_JOB_SEQ (ID BIGINT NOT NULL) type=MYISAM; +CREATE TABLE BATCH_JOB_SEQ (ID BIGINT NOT NULL) ENGINE=MYISAM; INSERT INTO BATCH_JOB_SEQ values(0); diff --git a/spring-batch-core/src/main/resources/schema-oracle10g.sql b/spring-batch-core/src/main/resources/schema-oracle10g.sql index 4648a4d27..7445c11ca 100644 --- a/spring-batch-core/src/main/resources/schema-oracle10g.sql +++ b/spring-batch-core/src/main/resources/schema-oracle10g.sql @@ -1,6 +1,7 @@ -- Autogenerated: do not edit this file -DROP TABLE BATCH_EXECUTION_CONTEXT ; +DROP TABLE BATCH_STEP_EXECUTION_CONTEXT ; +DROP TABLE BATCH_JOB_EXECUTION_CONTEXT ; DROP TABLE BATCH_STEP_EXECUTION ; DROP TABLE BATCH_JOB_EXECUTION ; DROP TABLE BATCH_JOB_PARAMS ; @@ -68,16 +69,20 @@ CREATE TABLE BATCH_STEP_EXECUTION ( references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; -CREATE TABLE BATCH_EXECUTION_CONTEXT ( - EXECUTION_ID NUMBER(38) NOT NULL, - DISCRIMINATOR VARCHAR2(1) NOT NULL, - TYPE_CD VARCHAR2(6) NOT NULL, - KEY_NAME VARCHAR2(1000) NOT NULL, - STRING_VAL VARCHAR2(1000) , - DATE_VAL TIMESTAMP DEFAULT NULL, - LONG_VAL NUMBER(38) , - DOUBLE_VAL NUMBER , - OBJECT_VAL BLOB +CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( + STEP_EXECUTION_ID NUMBER(38) NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR2(2500) NOT NULL, + SERIALIZED_CONTEXT CLOB , + constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) + references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) +) ; + +CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( + JOB_EXECUTION_ID NUMBER(38) NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR2(2500) NOT NULL, + SERIALIZED_CONTEXT CLOB , + constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) + references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; diff --git a/spring-batch-core/src/main/resources/schema-postgresql.sql b/spring-batch-core/src/main/resources/schema-postgresql.sql index 8255504fd..386de0730 100644 --- a/spring-batch-core/src/main/resources/schema-postgresql.sql +++ b/spring-batch-core/src/main/resources/schema-postgresql.sql @@ -1,6 +1,7 @@ -- Autogenerated: do not edit this file -DROP TABLE BATCH_EXECUTION_CONTEXT ; +DROP TABLE BATCH_STEP_EXECUTION_CONTEXT ; +DROP TABLE BATCH_JOB_EXECUTION_CONTEXT ; DROP TABLE BATCH_STEP_EXECUTION ; DROP TABLE BATCH_JOB_EXECUTION ; DROP TABLE BATCH_JOB_PARAMS ; @@ -68,16 +69,20 @@ CREATE TABLE BATCH_STEP_EXECUTION ( references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; -CREATE TABLE BATCH_EXECUTION_CONTEXT ( - EXECUTION_ID BIGINT NOT NULL, - DISCRIMINATOR VARCHAR(1) NOT NULL, - TYPE_CD VARCHAR(6) NOT NULL, - KEY_NAME VARCHAR(1000) NOT NULL, - STRING_VAL VARCHAR(1000) , - DATE_VAL TIMESTAMP DEFAULT NULL, - LONG_VAL BIGINT , - DOUBLE_VAL DOUBLE PRECISION , - OBJECT_VAL BYTEA +CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( + STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT BYTEA , + constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) + references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) +) ; + +CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( + JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT BYTEA , + constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) + references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ; diff --git a/spring-batch-core/src/main/resources/schema-sqlserver.sql b/spring-batch-core/src/main/resources/schema-sqlserver.sql index 5d1330039..dc84d5148 100644 --- a/spring-batch-core/src/main/resources/schema-sqlserver.sql +++ b/spring-batch-core/src/main/resources/schema-sqlserver.sql @@ -1,6 +1,7 @@ -- Autogenerated: do not edit this file -DROP TABLE BATCH_EXECUTION_CONTEXT ; +DROP TABLE BATCH_STEP_EXECUTION_CONTEXT ; +DROP TABLE BATCH_JOB_EXECUTION_CONTEXT ; DROP TABLE BATCH_STEP_EXECUTION ; DROP TABLE BATCH_JOB_EXECUTION ; DROP TABLE BATCH_JOB_PARAMS ; @@ -68,16 +69,20 @@ CREATE TABLE BATCH_STEP_EXECUTION ( references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; -CREATE TABLE BATCH_EXECUTION_CONTEXT ( - EXECUTION_ID BIGINT NOT NULL, - DISCRIMINATOR VARCHAR(1) NOT NULL, - TYPE_CD VARCHAR(6) NOT NULL, - KEY_NAME VARCHAR(1000) NOT NULL, - STRING_VAL VARCHAR(1000) , - DATE_VAL DATETIME DEFAULT NULL, - LONG_VAL BIGINT , - DOUBLE_VAL DOUBLE PRECISION , - OBJECT_VAL IMAGE +CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( + STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT TEXT , + constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) + references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) +) ; + +CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( + JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT TEXT , + constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) + references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE TABLE BATCH_STEP_EXECUTION_SEQ (ID BIGINT IDENTITY); diff --git a/spring-batch-core/src/main/resources/schema-sybase.sql b/spring-batch-core/src/main/resources/schema-sybase.sql index 01dbca5fb..0f2da3e3b 100644 --- a/spring-batch-core/src/main/resources/schema-sybase.sql +++ b/spring-batch-core/src/main/resources/schema-sybase.sql @@ -1,6 +1,7 @@ -- Autogenerated: do not edit this file -DROP TABLE BATCH_EXECUTION_CONTEXT ; +DROP TABLE BATCH_STEP_EXECUTION_CONTEXT ; +DROP TABLE BATCH_JOB_EXECUTION_CONTEXT ; DROP TABLE BATCH_STEP_EXECUTION ; DROP TABLE BATCH_JOB_EXECUTION ; DROP TABLE BATCH_JOB_PARAMS ; @@ -68,16 +69,20 @@ CREATE TABLE BATCH_STEP_EXECUTION ( references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; -CREATE TABLE BATCH_EXECUTION_CONTEXT ( - EXECUTION_ID BIGINT NOT NULL, - DISCRIMINATOR VARCHAR(1) NOT NULL, - TYPE_CD VARCHAR(6) NOT NULL, - KEY_NAME VARCHAR(1000) NOT NULL, - STRING_VAL VARCHAR(1000) NULL, - DATE_VAL DATETIME DEFAULT NULL, - LONG_VAL BIGINT NULL, - DOUBLE_VAL DOUBLE PRECISION NULL, - OBJECT_VAL IMAGE NULL +CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( + STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT TEXT NULL, + constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) + references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) +) ; + +CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( + JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, + SHORT_CONTEXT VARCHAR(2500) NOT NULL, + SERIALIZED_CONTEXT TEXT NULL, + constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) + references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE TABLE BATCH_STEP_EXECUTION_SEQ (ID BIGINT IDENTITY); diff --git a/spring-batch-core/src/main/sql/destroy.sql.vpp b/spring-batch-core/src/main/sql/destroy.sql.vpp index f29192333..1c95ce2a8 100644 --- a/spring-batch-core/src/main/sql/destroy.sql.vpp +++ b/spring-batch-core/src/main/sql/destroy.sql.vpp @@ -1,4 +1,5 @@ -DROP TABLE $!{IFEXISTSBEFORE} BATCH_EXECUTION_CONTEXT $!{IFEXISTS}; +DROP TABLE $!{IFEXISTSBEFORE} BATCH_STEP_EXECUTION_CONTEXT $!{IFEXISTS}; +DROP TABLE $!{IFEXISTSBEFORE} BATCH_JOB_EXECUTION_CONTEXT $!{IFEXISTS}; DROP TABLE $!{IFEXISTSBEFORE} BATCH_STEP_EXECUTION $!{IFEXISTS}; DROP TABLE $!{IFEXISTSBEFORE} BATCH_JOB_EXECUTION $!{IFEXISTS}; DROP TABLE $!{IFEXISTSBEFORE} BATCH_JOB_PARAMS $!{IFEXISTS}; diff --git a/spring-batch-core/src/main/sql/hsqldb.properties b/spring-batch-core/src/main/sql/hsqldb.properties index e5ff67c12..8cf391d9e 100644 --- a/spring-batch-core/src/main/sql/hsqldb.properties +++ b/spring-batch-core/src/main/sql/hsqldb.properties @@ -5,7 +5,7 @@ IDENTITY = IDENTITY IFEXISTS = IF EXISTS DOUBLE = DOUBLE PRECISION BLOB = LONGVARBINARY -CLOB = CLOB +CLOB = LONGVARCHAR TIMESTAMP = TIMESTAMP VARCHAR = VARCHAR # for generating drop statements... diff --git a/spring-batch-core/src/main/sql/mysql.properties b/spring-batch-core/src/main/sql/mysql.properties index baad0f9d5..470ca6bc1 100644 --- a/spring-batch-core/src/main/sql/mysql.properties +++ b/spring-batch-core/src/main/sql/mysql.properties @@ -3,11 +3,11 @@ platform=oracle10g BIGINT = BIGINT IDENTITY = GENERATED = -VOODOO = type=InnoDB +VOODOO = ENGINE=InnoDB IFEXISTSBEFORE = IF EXISTS DOUBLE = DOUBLE PRECISION BLOB = BLOB -CLOB = CLOB +CLOB = TEXT TIMESTAMP = DATETIME VARCHAR = VARCHAR # for generating drop statements... diff --git a/spring-batch-core/src/main/sql/mysql.vpp b/spring-batch-core/src/main/sql/mysql.vpp index 263d6934f..1abd1f003 100644 --- a/spring-batch-core/src/main/sql/mysql.vpp +++ b/spring-batch-core/src/main/sql/mysql.vpp @@ -1,4 +1,4 @@ -#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT NOT NULL) type=MYISAM; +#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT NOT NULL) ENGINE=MYISAM; INSERT INTO ${name} values(0); #end #macro (notnull $name $type)MODIFY COLUMN ${name} ${type} NOT NULL#end diff --git a/spring-batch-core/src/main/sql/tables-context.sql.vpp b/spring-batch-core/src/main/sql/tables-context.sql.vpp index f588b355f..69b3403ab 100644 --- a/spring-batch-core/src/main/sql/tables-context.sql.vpp +++ b/spring-batch-core/src/main/sql/tables-context.sql.vpp @@ -1,11 +1,15 @@ -CREATE TABLE BATCH_EXECUTION_CONTEXT ( - EXECUTION_ID ${BIGINT} NOT NULL, - DISCRIMINATOR ${VARCHAR}(1) NOT NULL, - TYPE_CD ${VARCHAR}(6) NOT NULL, - KEY_NAME ${VARCHAR}(1000) NOT NULL, - STRING_VAL ${VARCHAR}(1000) $!{NULL}, - DATE_VAL ${TIMESTAMP} DEFAULT NULL, - LONG_VAL ${BIGINT} $!{NULL}, - DOUBLE_VAL ${DOUBLE} $!{NULL}, - OBJECT_VAL ${BLOB} $!{NULL} +CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( + STEP_EXECUTION_ID ${BIGINT} NOT NULL PRIMARY KEY, + SHORT_CONTEXT ${VARCHAR}(2500) NOT NULL, + SERIALIZED_CONTEXT ${CLOB} $!{NULL}, + constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) + references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) +) $!{VOODOO}; + +CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( + JOB_EXECUTION_ID ${BIGINT} NOT NULL PRIMARY KEY, + SHORT_CONTEXT ${VARCHAR}(2500) NOT NULL, + SERIALIZED_CONTEXT ${CLOB} $!{NULL}, + constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) + references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) $!{VOODOO}; diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextDaoTests.java index 7babacaf2..26672b15d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextDaoTests.java @@ -11,6 +11,7 @@ import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.StepExecution; import org.springframework.batch.item.ExecutionContext; import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.transaction.annotation.Transactional; /** @@ -18,17 +19,51 @@ import org.springframework.transaction.annotation.Transactional; */ public abstract class AbstractExecutionContextDaoTests extends AbstractTransactionalJUnit4SpringContextTests { - private ExecutionContextDao dao; + private JobInstanceDao jobInstanceDao; + + private JobExecutionDao jobExecutionDao; - private JobExecution jobExecution = new JobExecution(new JobInstance(1L, new JobParameters(), "jobName"), 1L); + private StepExecutionDao stepExecutionDao; - private StepExecution stepExecution = new StepExecution("stepName", jobExecution, 1L); + private ExecutionContextDao contextDao; + + private JobExecution jobExecution; + + private StepExecution stepExecution; @Before public void setUp() { - dao = getExecutionContextDao(); + jobInstanceDao = getJobInstanceDao(); + jobExecutionDao = getJobExecutionDao(); + stepExecutionDao = getStepExecutionDao(); + contextDao = getExecutionContextDao(); + + JobInstance ji = jobInstanceDao.createJobInstance("testJob", new JobParameters()); + jobExecution = new JobExecution(ji); + jobExecutionDao.saveJobExecution(jobExecution); + stepExecution = new StepExecution("stepName", jobExecution); + stepExecutionDao.saveStepExecution(stepExecution); + } + /** + * @return Configured {@link ExecutionContextDao} implementation ready for + * use. + */ + protected abstract JobExecutionDao getJobExecutionDao(); + + /** + * @return Configured {@link ExecutionContextDao} implementation ready for + * use. + */ + protected abstract JobInstanceDao getJobInstanceDao(); + + /** + * @return Configured {@link ExecutionContextDao} implementation ready for + * use. + */ + protected abstract StepExecutionDao getStepExecutionDao(); + /** * @return Configured {@link ExecutionContextDao} implementation ready for * use. @@ -41,9 +76,9 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti ExecutionContext ctx = new ExecutionContext(Collections. singletonMap("key", "value")); jobExecution.setExecutionContext(ctx); - dao.persistExecutionContext(jobExecution); + contextDao.persistExecutionContext(jobExecution); - ExecutionContext retrieved = dao.getExecutionContext(jobExecution); + ExecutionContext retrieved = contextDao.getExecutionContext(jobExecution); assertEquals(ctx, retrieved); } @@ -53,9 +88,9 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti ExecutionContext ctx = new ExecutionContext(); jobExecution.setExecutionContext(ctx); - dao.persistExecutionContext(jobExecution); + contextDao.persistExecutionContext(jobExecution); - ExecutionContext retrieved = dao.getExecutionContext(jobExecution); + ExecutionContext retrieved = contextDao.getExecutionContext(jobExecution); assertEquals(ctx, retrieved); } @@ -66,12 +101,12 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti ExecutionContext ctx = new ExecutionContext(Collections . singletonMap("key", "value")); jobExecution.setExecutionContext(ctx); - dao.persistExecutionContext(jobExecution); + contextDao.persistExecutionContext(jobExecution); ctx.putLong("longKey", 7); - dao.persistExecutionContext(jobExecution); + contextDao.persistExecutionContext(jobExecution); - ExecutionContext retrieved = dao.getExecutionContext(jobExecution); + ExecutionContext retrieved = contextDao.getExecutionContext(jobExecution); assertEquals(ctx, retrieved); assertEquals(7, retrieved.getLong("longKey")); } @@ -82,9 +117,9 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti ExecutionContext ctx = new ExecutionContext(Collections. singletonMap("key", "value")); stepExecution.setExecutionContext(ctx); - dao.persistExecutionContext(stepExecution); + contextDao.persistExecutionContext(stepExecution); - ExecutionContext retrieved = dao.getExecutionContext(stepExecution); + ExecutionContext retrieved = contextDao.getExecutionContext(stepExecution); assertEquals(ctx, retrieved); } @@ -94,9 +129,9 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti ExecutionContext ctx = new ExecutionContext(); stepExecution.setExecutionContext(ctx); - dao.persistExecutionContext(stepExecution); + contextDao.persistExecutionContext(stepExecution); - ExecutionContext retrieved = dao.getExecutionContext(stepExecution); + ExecutionContext retrieved = contextDao.getExecutionContext(stepExecution); assertEquals(ctx, retrieved); } @@ -106,12 +141,12 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti ExecutionContext ctx = new ExecutionContext(Collections. singletonMap("key", "value")); stepExecution.setExecutionContext(ctx); - dao.persistExecutionContext(stepExecution); + contextDao.persistExecutionContext(stepExecution); ctx.putLong("longKey", 7); - dao.persistExecutionContext(stepExecution); + contextDao.persistExecutionContext(stepExecution); - ExecutionContext retrieved = dao.getExecutionContext(stepExecution); + ExecutionContext retrieved = contextDao.getExecutionContext(stepExecution); assertEquals(ctx, retrieved); assertEquals(7, retrieved.getLong("longKey")); } @@ -123,8 +158,8 @@ public abstract class AbstractExecutionContextDaoTests extends AbstractTransacti ExecutionContext ec = new ExecutionContext(); ec.put("intValue", new Integer(343232)); stepExecution.setExecutionContext(ec); - dao.persistExecutionContext(stepExecution); - ExecutionContext restoredEc = dao.getExecutionContext(stepExecution); + contextDao.persistExecutionContext(stepExecution); + ExecutionContext restoredEc = contextDao.getExecutionContext(stepExecution); assertEquals(ec, restoredEc); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java index f0391083c..52d61eac4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java @@ -8,6 +8,21 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(locations = {"sql-dao-test.xml"}) public class JdbcExecutionContextDaoTests extends AbstractExecutionContextDaoTests { + @Override + protected JobInstanceDao getJobInstanceDao() { + return (JobInstanceDao) applicationContext.getBean("jobInstanceDao", JobInstanceDao.class); + } + + @Override + protected JobExecutionDao getJobExecutionDao() { + return (JobExecutionDao) applicationContext.getBean("jobExecutionDao", JdbcJobExecutionDao.class); + } + + @Override + protected StepExecutionDao getStepExecutionDao() { + return (StepExecutionDao) applicationContext.getBean("stepExecutionDao", StepExecutionDao.class); + } + @Override protected ExecutionContextDao getExecutionContextDao() { return (ExecutionContextDao) applicationContext.getBean("executionContextDao", JdbcExecutionContextDao.class); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDaoTests.java index fed66f78b..52456c7df 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDaoTests.java @@ -22,7 +22,7 @@ public class JdbcJobExecutionDaoTests extends AbstractJobExecutionDaoTests { @Override protected JobExecutionDao getJobExecutionDao() { - deleteFromTables("BATCH_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION", "BATCH_JOB_PARAMS", + deleteFromTables("BATCH_JOB_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION", "BATCH_JOB_PARAMS", "BATCH_JOB_INSTANCE"); // job instance needs to exist before job execution can be created diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java index a89d86200..5b4762937 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java @@ -14,7 +14,7 @@ import org.junit.runner.RunWith; public class JdbcJobInstanceDaoTests extends AbstractJobInstanceDaoTests { protected JobInstanceDao getJobInstanceDao() { - deleteFromTables("BATCH_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION", + deleteFromTables("BATCH_JOB_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION", "BATCH_JOB_PARAMS", "BATCH_JOB_INSTANCE"); return (JobInstanceDao) applicationContext.getBean("jobInstanceDao"); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDaoTests.java index 6bac7d2f3..2b60a210b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDaoTests.java @@ -20,7 +20,7 @@ public class JdbcStepExecutionDaoTests extends AbstractStepExecutionDaoTests { } protected JobRepository getJobRepository() { - deleteFromTables("BATCH_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION", + deleteFromTables("BATCH_JOB_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION", "BATCH_JOB_PARAMS", "BATCH_JOB_INSTANCE"); return (JobRepository) applicationContext.getBean("jobRepository"); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/MapExecutionContextDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/MapExecutionContextDaoTests.java index 3f8b54217..f3178f693 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/MapExecutionContextDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/MapExecutionContextDaoTests.java @@ -9,6 +9,24 @@ import org.junit.runner.RunWith; @RunWith(JUnit4ClassRunner.class) public class MapExecutionContextDaoTests extends AbstractExecutionContextDaoTests { + @Override + protected JobInstanceDao getJobInstanceDao() { + MapJobInstanceDao.clear(); + return new MapJobInstanceDao(); + } + + @Override + protected JobExecutionDao getJobExecutionDao() { + MapJobExecutionDao.clear(); + return new MapJobExecutionDao(); + } + + @Override + protected StepExecutionDao getStepExecutionDao() { + MapStepExecutionDao.clear(); + return new MapStepExecutionDao(); + } + @Override protected ExecutionContextDao getExecutionContextDao() { return new MapExecutionContextDao(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java index 1505efde8..51bbd049a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java @@ -62,7 +62,7 @@ public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { sql.append(" FROM ").append(getFromClause()); sql.append(getWhereClause() == null ? "" : " WHERE " + getWhereClause()); sql.append(" ORDER BY ").append(getSortKey()).append(" ASC"); - sql.append(" LIMIT ").append(offset).append(" 1"); + sql.append(" LIMIT ").append(offset).append(", 1"); return sql.toString(); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java index d6d03381d..43db6fdb5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java @@ -44,7 +44,7 @@ public class MySqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvide @Test @Override public void testGenerateJumpToItemQuery() { - String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 99 1"; + String sql = "SELECT id AS SORT_KEY FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 99, 1"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); Assert.assertEquals("", sql, s); } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/JdbcJobRepositoryTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/JdbcJobRepositoryTests.java index dbc49c475..538193249 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/JdbcJobRepositoryTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/JdbcJobRepositoryTests.java @@ -89,7 +89,8 @@ public class JdbcJobRepositoryTests { public void onSetUpInTransaction() throws Exception { job = new JobSupport("test-job"); job.setRestartable(true); - simpleJdbcTemplate.update("DELETE FROM BATCH_EXECUTION_CONTEXT"); + simpleJdbcTemplate.update("DELETE FROM BATCH_STEP_EXECUTION_CONTEXT"); + simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION_CONTEXT"); simpleJdbcTemplate.update("DELETE FROM BATCH_STEP_EXECUTION"); simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_EXECUTION"); simpleJdbcTemplate.update("DELETE FROM BATCH_JOB_PARAMS");