diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/BatchHibernateInterceptor.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/BatchHibernateInterceptor.java new file mode 100644 index 000000000..257f69e4d --- /dev/null +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/BatchHibernateInterceptor.java @@ -0,0 +1,115 @@ +package org.springframework.batch.execution.repository.dao; + +import java.io.Serializable; + +import org.hibernate.EmptyInterceptor; +import org.hibernate.type.Type; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobIdentifier; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * Hibernate interceptor for batch meta data. It can distinguish between the + * various {@link JobIdentifier} strategies in a {@link JobInstance}, and can + * truncate the exit descriptions. Its main task is to return the correct entity + * name for a {@link JobInstance} based on the type of {@link JobIdentifier} + * used. There is necessarily some tight coupling between this and the Hibernate + * mappings for {@link JobInstance} because the map from {@link JobIdentifier} + * type to entity name is in both places. + * + * @author Dave Syer + * + */ +public class BatchHibernateInterceptor extends EmptyInterceptor implements + InitializingBean { + + /** + * + */ + private static final int EXIT_MESSAGE_LENGTH = 250; + private EntityNameLocator entityNameLocator; + + /** + * Public setter for the {@link EntityNameLocator} property. + * + * @param entityNameLocator + * the entityNameLocator to set + */ + public void setEntityNameLocator(EntityNameLocator entityNameLocator) { + this.entityNameLocator = entityNameLocator; + } + + /** + * Check mandatory properties ({@link #entityNameLocator}). + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert + .notNull(entityNameLocator, + "EntityNameLocator must be provided."); + } + + /** + * If the object is a {@link JobInstance} search the identifier types for an + * entity name based on the {@link JobIdentifier} type. Fall back to + * SimpleJobIdentifier if the value is not found. + * + * @see org.hibernate.EmptyInterceptor#getEntityName(java.lang.Object) + */ + public String getEntityName(Object object) { + if (object instanceof JobInstance) { + JobInstance instance = (JobInstance) object; + return entityNameLocator + .locate(instance.getIdentifier().getClass()); + } + return super.getEntityName(object); + } + + /** + * Ensure that {@link JobExecution} and {@link StepExecution} have exit + * status with legal description (not too long). + * + * @see org.hibernate.EmptyInterceptor#onFlushDirty(java.lang.Object, + * java.io.Serializable, java.lang.Object[], java.lang.Object[], + * java.lang.String[], org.hibernate.type.Type[]) + */ + public boolean onFlushDirty(Object entity, Serializable id, + Object[] currentState, Object[] previousState, + String[] propertyNames, Type[] types) { + + if (entity instanceof StepExecution || entity instanceof JobExecution) { + int index = findExitStatus(propertyNames); + ExitStatus status = (ExitStatus) currentState[index]; + String description = status == null ? "" : status + .getExitDescription(); + if (description.length() > EXIT_MESSAGE_LENGTH) { + status = status.addExitDescription(description.substring(0, + EXIT_MESSAGE_LENGTH)); + currentState[index] = status; + // state was modified... + return true; + } + } + + return false; + } + + /** + * @param propertyNames + * @return + */ + private int findExitStatus(String[] propertyNames) { + for (int i = 0; i < propertyNames.length; i++) { + if ("exitStatus".equals(propertyNames[i])) { + return i; + } + } + return -1; + } + +} diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptor.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptor.java deleted file mode 100644 index a9947c759..000000000 --- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptor.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.springframework.batch.execution.repository.dao; - -import org.hibernate.EmptyInterceptor; -import org.springframework.batch.core.domain.JobIdentifier; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * Hibernate interceptor that can distinguish between the various - * {@link JobIdentifier} strategies in a {@link JobInstance}. Its task is to - * return the correct entity name based on the type of {@link JobIdentifier} - * used. There is necessarily some tight coupling between this and the Hibernate - * mappings for {@link JobInstance} because the map from {@link JobIdentifier} - * type to entity name is in both places. - * - * - * @author Dave Syer - * - */ -public class EntityNameInterceptor extends EmptyInterceptor implements InitializingBean { - - private EntityNameLocator entityNameLocator; - - /** - * Public setter for the {@link EntityNameLocator} property. - * - * @param entityNameLocator the entityNameLocator to set - */ - public void setEntityNameLocator(EntityNameLocator entityNameLocator) { - this.entityNameLocator = entityNameLocator; - } - - /** - * Check mandatory properties ({@link #entityNameLocator}). - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(entityNameLocator, "EntityNameLocator must be provided."); - } - - /** - * If the object is a {@link JobInstance} search the identifier types for an - * entity name based on the {@link JobIdentifier} type. Fall back to - * SimpleJobIdentifier if the value is not found. - * - * @see org.hibernate.EmptyInterceptor#getEntityName(java.lang.Object) - */ - public String getEntityName(Object object) { - if (object instanceof JobInstance) { - JobInstance instance = (JobInstance) object; - return entityNameLocator - .locate(instance.getIdentifier().getClass()); - } - return super.getEntityName(object); - } - -} diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java index 7e5fd60f3..f0b7df81e 100644 --- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlJobDao.java @@ -21,6 +21,8 @@ import java.sql.SQLException; import java.sql.Types; import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.domain.BatchStatus; import org.springframework.batch.core.domain.JobExecution; import org.springframework.batch.core.domain.JobIdentifier; @@ -49,6 +51,8 @@ import org.springframework.util.StringUtils; * @author Dave Syer */ public class SqlJobDao implements JobDao, InitializingBean { + + protected static final Log logger = LogFactory.getLog(SqlJobDao.class); /** * Default value for the table prefix property. @@ -78,6 +82,8 @@ public class SqlJobDao implements JobDao, InitializingBean { private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE ID=?"; + private static final int EXIT_MESSAGE_LENGTH = 250; + private JdbcTemplate jdbcTemplate; private DataFieldMaxValueIncrementer jobIncrementer; @@ -207,11 +213,16 @@ public class SqlJobDao implements JobDao, InitializingBean { validateJobExecution(jobExecution); + String exitDescription = jobExecution.getExitStatus().getExitDescription(); + if (exitDescription!=null && exitDescription.length()>EXIT_MESSAGE_LENGTH) { + exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH); + logger.debug("Truncating long message before update of JobExecution: "+jobExecution); + } Object[] parameters = new Object[] { jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(), jobExecution.getExitStatus().isContinuable() ? "Y" : "N", jobExecution.getExitStatus().getExitCode(), - jobExecution.getExitStatus().getExitDescription(), + exitDescription, jobExecution.getId() }; if (jobExecution.getId() == null) { diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java index 4254f0b31..fe8a97dbc 100644 --- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java +++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/SqlStepDao.java @@ -22,6 +22,8 @@ import java.sql.Types; import java.util.List; import java.util.Properties; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.domain.BatchStatus; import org.springframework.batch.core.domain.JobExecution; import org.springframework.batch.core.domain.JobInstance; @@ -55,10 +57,13 @@ import org.springframework.util.StringUtils; * on the step dao java docs as well. * * @author Lucas Ward + * @author Dave Syer * @see StepDao */ public class SqlStepDao implements StepDao, InitializingBean { + protected static final Log logger = LogFactory.getLog(SqlStepDao.class); + // Step SQL statements private static final String FIND_STEPS = "SELECT ID, STEP_NAME, STATUS, RESTART_DATA from %PREFIX%STEP where JOB_ID = ?"; @@ -84,6 +89,8 @@ public class SqlStepDao implements StepDao, InitializingBean { private static final String FIND_STEP_EXECUTIONS = "SELECT ID, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT," + " TASK_COUNT, TASK_STATISTICS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%STEP_EXECUTION where STEP_ID = ?"; + private static final int EXIT_MESSAGE_LENGTH = 250; + private JdbcOperations jdbcTemplate; private JobDao jobDao; @@ -314,6 +321,12 @@ public class SqlStepDao implements StepDao, InitializingBean { // return; // throw exception? // } + String exitDescription = stepExecution.getExitStatus().getExitDescription(); + if (exitDescription!=null && exitDescription.length()>EXIT_MESSAGE_LENGTH) { + exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH); + logger.debug("Truncating long message before update of StepExecution: "+stepExecution); + } + Object[] parameters = new Object[] { stepExecution.getStartTime(), stepExecution.getEndTime(), @@ -324,7 +337,7 @@ public class SqlStepDao implements StepDao, InitializingBean { .getStatistics()), stepExecution.getExitStatus().isContinuable() ? "Y" : "N", stepExecution.getExitStatus().getExitCode(), - stepExecution.getExitStatus().getExitDescription(), + exitDescription, stepExecution.getId() }; jdbcTemplate .update(getQuery(UPDATE_STEP_EXECUTION), parameters, diff --git a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobExecution.hbm.xml b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobExecution.hbm.xml index 33133314b..ce568d90d 100644 --- a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobExecution.hbm.xml +++ b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobExecution.hbm.xml @@ -15,11 +15,11 @@ - + - - + + diff --git a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepExecution.hbm.xml b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepExecution.hbm.xml index 67e836399..75806ce03 100644 --- a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepExecution.hbm.xml +++ b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepExecution.hbm.xml @@ -16,14 +16,14 @@ - + - + - - + + diff --git a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepInstance.hbm.xml b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepInstance.hbm.xml index ffca30f2f..4e2d9c9df 100644 --- a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepInstance.hbm.xml +++ b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/StepInstance.hbm.xml @@ -16,8 +16,8 @@ + column="RESTART_DATA" length="250"/> + insert="false" column="STATUS" length="10"/> diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/BatchHibernateInterceptorTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/BatchHibernateInterceptorTests.java new file mode 100644 index 000000000..3e150dd78 --- /dev/null +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/BatchHibernateInterceptorTests.java @@ -0,0 +1,82 @@ +package org.springframework.batch.execution.repository.dao; + +import junit.framework.TestCase; + +import org.hibernate.type.Type; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; +import org.springframework.batch.repeat.ExitStatus; + +public class BatchHibernateInterceptorTests extends TestCase { + + public static final String LONG_STRING = "A very long description: \n" + + "Nov 16 20:10:42 util.JDBCExceptionReporter 78 - Data truncation: Data too long for column 'exit_message' at row 1\n" + + "Nov 16 20:10:43 def.AbstractFlushingEventListener 301 - Could not synchronize database state with session \n" + + "org.hibernate.exception.DataException: could not update: [org.springframework.batch.core.domain.JobExecution#67]\n" + + " at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:77)\n"; + + private BatchHibernateInterceptor interceptor = new BatchHibernateInterceptor(); + + /* (non-Javadoc) + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + interceptor.setEntityNameLocator(new EntityNameLocator() { + public String locate(Class clz) { + return "foo"; + } + }); + } + + public void testAfterPropertiesSet() throws Exception { + interceptor = new BatchHibernateInterceptor(); + try { + interceptor.afterPropertiesSet(); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + } + } + + public void testGetEntityName() { + JobInstance job = new JobInstance(new ScheduledJobIdentifier("foo")); + assertEquals("foo", interceptor.getEntityName(job)); + } + + public void testGetEntityNameForNonJobInstance() { + Object job = new Object(); + assertEquals(null, interceptor.getEntityName(job)); + } + + public void testOnFlushDirtyWithJobInstance() throws Exception { + JobInstance job = new JobInstance(new ScheduledJobIdentifier("foo")); + assertFalse(interceptor.onFlushDirty(job, null, new Object[1], new Object[1], new String[] {"exitStatus"}, new Type[1])); + } + + public void testOnFlushDirtyWithShortDescription() throws Exception { + JobExecution execution = new JobExecution(new JobInstance(new ScheduledJobIdentifier("foo"))); + execution.setExitStatus(ExitStatus.UNKNOWN.addExitDescription("bar")); + assertFalse(interceptor.onFlushDirty(execution, null, new Object[] {execution.getExitStatus()}, new Object[1], new String[] {"exitStatus"}, new Type[1])); + } + + public void testOnFlushDirtyWithLongDescription() throws Exception { + JobExecution execution = new JobExecution(new JobInstance(new ScheduledJobIdentifier("foo"))); + execution.setExitStatus(ExitStatus.UNKNOWN.addExitDescription(LONG_STRING)); + Object[] state = new Object[] {execution.getExitStatus()}; + assertTrue(interceptor.onFlushDirty(execution, null, state, new Object[1], new String[] {"exitStatus"}, new Type[1])); + assertEquals(250, ((ExitStatus) state[0]).getExitDescription().length()); + } + + public void testOnFlushDirtyWithMissingExitStatusProperty() throws Exception { + JobExecution execution = new JobExecution(new JobInstance(new ScheduledJobIdentifier("foo"))); + execution.setExitStatus(ExitStatus.UNKNOWN.addExitDescription("bar")); + try { + interceptor.onFlushDirty(execution, null, new Object[] {execution.getExitStatus()}, new Object[1], new String[1], new Type[1]); + fail("Expected ArrayIndexOutOfBoundsException"); + } catch (ArrayIndexOutOfBoundsException e) { + // expected; + } + } +} diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptorTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptorTests.java deleted file mode 100644 index cdccc46c9..000000000 --- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptorTests.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.springframework.batch.execution.repository.dao; - -import junit.framework.TestCase; - -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; - -public class EntityNameInterceptorTests extends TestCase { - - private EntityNameInterceptor interceptor = new EntityNameInterceptor(); - - /* (non-Javadoc) - * @see junit.framework.TestCase#setUp() - */ - protected void setUp() throws Exception { - super.setUp(); - interceptor.setEntityNameLocator(new EntityNameLocator() { - public String locate(Class clz) { - return "foo"; - } - }); - } - - public void testGetEntityName() { - JobInstance job = new JobInstance(new ScheduledJobIdentifier("foo")); - assertEquals("foo", interceptor.getEntityName(job)); - } - -} diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateJobDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateJobDaoTests.java index d7a1a7792..b6ce2c099 100644 --- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateJobDaoTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateJobDaoTests.java @@ -26,10 +26,13 @@ import org.springframework.batch.core.domain.JobIdentifier; import org.springframework.batch.core.domain.JobInstance; import org.springframework.batch.core.runtime.SimpleJobIdentifier; import org.springframework.batch.execution.runtime.ScheduledJobIdentifier; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.util.ClassUtils; public class HibernateJobDaoTests extends AbstractJobDaoTests { + private static final String LONG_STRING = BatchHibernateInterceptorTests.LONG_STRING; + private SessionFactory sessionFactory; protected String[] getConfigLocations() { @@ -89,6 +92,22 @@ public class HibernateJobDaoTests extends AbstractJobDaoTests { assertEquals(simpleJob, testJob); } + public void testUpdateJobExecutionWithLongExitCode() { + + assertTrue(LONG_STRING.length()>250); + jobExecution.setExitStatus(ExitStatus.FINISHED.addExitDescription(LONG_STRING)); + jobDao.update(jobExecution); + + sessionFactory.getCurrentSession().flush(); + + List executions = jdbcTemplate.queryForList( + "SELECT * FROM BATCH_JOB_EXECUTION where JOB_ID=?", + new Object[] { job.getId() }); + assertEquals(1, executions.size()); + assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)) + .get("EXIT_MESSAGE")); + } + public void testNullIdentifierName() { JobIdentifier simpleIdentifier = new SimpleJobIdentifier(null); diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateStepDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateStepDaoTests.java index cabd823ea..f4a6648c6 100644 --- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateStepDaoTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateStepDaoTests.java @@ -26,11 +26,13 @@ import org.springframework.batch.core.domain.BatchStatus; import org.springframework.batch.core.domain.JobExecution; import org.springframework.batch.core.domain.StepExecution; import org.springframework.batch.core.domain.StepInstance; +import org.springframework.batch.repeat.ExitStatus; import org.springframework.batch.support.PropertiesConverter; import org.springframework.util.ClassUtils; public class HibernateStepDaoTests extends AbstractStepDaoTests { + private static final String LONG_STRING = BatchHibernateInterceptorTests.LONG_STRING; private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { @@ -78,5 +80,21 @@ public class HibernateStepDaoTests extends AbstractStepDaoTests { } + public void testUpdateStepExecutionWithLongDescription() { + + assertTrue(LONG_STRING.length()>250); + stepExecution.setExitStatus(ExitStatus.FINISHED.addExitDescription(LONG_STRING)); + stepDao.update(stepExecution); + + sessionFactory.getCurrentSession().flush(); + + List executions = jdbcTemplate.queryForList( + "SELECT * FROM BATCH_STEP_EXECUTION where STEP_ID=?", + new Object[] { step1.getId() }); + assertEquals(1, executions.size()); + assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)) + .get("EXIT_MESSAGE")); + + } } diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/SqlJobDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/SqlJobDaoTests.java index e3e68ecff..66993735a 100644 --- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/SqlJobDaoTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/SqlJobDaoTests.java @@ -1,10 +1,16 @@ package org.springframework.batch.execution.repository.dao; +import java.util.List; +import java.util.Map; + +import org.springframework.batch.repeat.ExitStatus; import org.springframework.dao.DataAccessException; public class SqlJobDaoTests extends AbstractJobDaoTests { + private static final String LONG_STRING = BatchHibernateInterceptorTests.LONG_STRING; + protected void onSetUpBeforeTransaction() throws Exception { ((SqlJobDao) jobDao).setTablePrefix(SqlJobDao.DEFAULT_TABLE_PREFIX); } @@ -19,4 +25,18 @@ public class SqlJobDaoTests extends AbstractJobDaoTests { } } + public void testUpdateJobExecutionWithLongExitCode() { + + assertTrue(LONG_STRING.length()>250); + jobExecution.setExitStatus(ExitStatus.FINISHED.addExitDescription(LONG_STRING)); + jobDao.update(jobExecution); + + List executions = jdbcTemplate.queryForList( + "SELECT * FROM BATCH_JOB_EXECUTION where JOB_ID=?", + new Object[] { job.getId() }); + assertEquals(1, executions.size()); + assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)) + .get("EXIT_MESSAGE")); + } + } diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/SqlStepDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/SqlStepDaoTests.java index 919211f35..f917d9b33 100644 --- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/SqlStepDaoTests.java +++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/SqlStepDaoTests.java @@ -1,9 +1,15 @@ package org.springframework.batch.execution.repository.dao; +import java.util.List; +import java.util.Map; + +import org.springframework.batch.repeat.ExitStatus; import org.springframework.dao.DataAccessException; public class SqlStepDaoTests extends AbstractStepDaoTests { + private static final String LONG_STRING = BatchHibernateInterceptorTests.LONG_STRING; + protected void onSetUpBeforeTransaction() throws Exception { ((SqlStepDao) stepDao).setTablePrefix(SqlJobDao.DEFAULT_TABLE_PREFIX); } @@ -18,4 +24,18 @@ public class SqlStepDaoTests extends AbstractStepDaoTests { } } + public void testUpdateStepExecutionWithLongExitCode() { + + assertTrue(LONG_STRING.length()>250); + stepExecution.setExitStatus(ExitStatus.FINISHED.addExitDescription(LONG_STRING)); + stepDao.update(stepExecution); + + List executions = jdbcTemplate.queryForList( + "SELECT * FROM BATCH_STEP_EXECUTION where STEP_ID=?", + new Object[] { step1.getId() }); + assertEquals(1, executions.size()); + assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)) + .get("EXIT_MESSAGE")); + } + } diff --git a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml index bf7573ea1..260707acb 100644 --- a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml +++ b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml @@ -6,7 +6,7 @@ - + diff --git a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-context.xml b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-context.xml index bbd74e1bc..a81bda566 100644 --- a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-context.xml +++ b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-context.xml @@ -27,7 +27,7 @@ + class="org.springframework.batch.execution.repository.dao.BatchHibernateInterceptor"> diff --git a/samples/src/main/resources/batch.properties b/samples/src/main/resources/batch.properties index 073b6d057..d787e6f81 100644 --- a/samples/src/main/resources/batch.properties +++ b/samples/src/main/resources/batch.properties @@ -1,7 +1,7 @@ # Placeholders batch.* # for HSQLDB: batch.jdbc.driver=org.hsqldb.jdbcDriver -batch.jdbc.url=jdbc:hsqldb:mem:testdb +batch.jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true # use this one for a separate server process (so you can inspect the results) # batch.jdbc.url=jdbc:hsqldb:hsql://localhost:9005/samples batch.jdbc.user=sa