OPEN - issue BATCH-207: exit_message too short for holding long exceptions
http://opensource.atlassian.com/projects/spring/browse/BATCH-207 Added onFlushDirty to the entity interceptor in hibernate (and changed its name so not specific to entity name - BatchHibernateInterceptor). Also truncating in Sql*Dao. Only exit description is given special treatment for now, and the length is fixed at 250 - hard-coded and tightly coupled with the hibernate mapping and DDL). Should be good enough for most scenarios.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
<many-to-one name="job" cascade="all" update="false" column="JOB_ID" access="field"/>
|
||||
<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="status" type="org.springframework.batch.execution.repository.dao.BatchStatusUserType" column="STATUS" length="10"/>
|
||||
<property name="exitStatus" type="org.springframework.batch.execution.repository.dao.ExitStatusUserType">
|
||||
<column name="CONTINUABLE"/>
|
||||
<column name="EXIT_CODE"/>
|
||||
<column name="EXIT_MESSAGE"/>
|
||||
<column name="EXIT_CODE" length="20"/>
|
||||
<column name="EXIT_MESSAGE" length="250"/>
|
||||
</property>
|
||||
</class>
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
<many-to-one name="jobExecution" cascade="all" update="false" column="JOB_EXECUTION_ID" access="field"/>
|
||||
<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="status" type="org.springframework.batch.execution.repository.dao.BatchStatusUserType" column="STATUS" length="10"/>
|
||||
<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="statistics" type="org.springframework.batch.execution.repository.dao.PropertiesUserType" column="TASK_STATISTICS" length="250"/>
|
||||
<property name="exitStatus" type="org.springframework.batch.execution.repository.dao.ExitStatusUserType">
|
||||
<column name="CONTINUABLE"/>
|
||||
<column name="EXIT_CODE"/>
|
||||
<column name="EXIT_MESSAGE"/>
|
||||
<column name="EXIT_CODE" length="20"/>
|
||||
<column name="EXIT_MESSAGE" length="250"/>
|
||||
</property>
|
||||
</class>
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
<property name="name" update="false" column="STEP_NAME" access="field"/>
|
||||
<property name="restartData"
|
||||
type="org.springframework.batch.execution.repository.dao.RestartDataUserType" insert="false"
|
||||
column="RESTART_DATA" />
|
||||
column="RESTART_DATA" length="250"/>
|
||||
<property name="status" type="org.springframework.batch.execution.repository.dao.BatchStatusUserType"
|
||||
insert="false" column="STATUS" />
|
||||
insert="false" column="STATUS" length="10"/>
|
||||
</class>
|
||||
</hibernate-mapping>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<property name="dataSource">
|
||||
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
||||
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
|
||||
<property name="url" value="jdbc:hsqldb:mem:testdb"/>
|
||||
<property name="url" value="jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="initScript" value="org/springframework/batch/execution/repository/dao/init.sql" />
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</property>
|
||||
<property name="entityInterceptor">
|
||||
<bean
|
||||
class="org.springframework.batch.execution.repository.dao.EntityNameInterceptor">
|
||||
class="org.springframework.batch.execution.repository.dao.BatchHibernateInterceptor">
|
||||
<property name="entityNameLocator" ref="entityNameLocator"/>
|
||||
</bean>
|
||||
</property>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user