BATCH-146: Changed my mind on the implementation, SimpleJobRepository (and DAOs) now throw Spring IncorrectResultSetSizeDataAccessException, rather than BatchRestartException.
This commit is contained in:
@@ -33,6 +33,7 @@ import org.springframework.batch.core.runtime.JobIdentifier;
|
||||
import org.springframework.batch.execution.repository.dao.JobDao;
|
||||
import org.springframework.batch.execution.repository.dao.StepDao;
|
||||
import org.springframework.batch.restart.GenericRestartData;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -116,8 +117,8 @@ public class SimpleJobRepository implements JobRepository {
|
||||
}
|
||||
else {
|
||||
// More than one job found, throw exception
|
||||
throw new BatchRestartException("Error restarting job, more than one JobInstance found for: "
|
||||
+ jobConfiguration.toString());
|
||||
throw new IncorrectResultSizeDataAccessException("Error restarting job, more than one JobInstance found for: "
|
||||
+ jobConfiguration.toString(), 1, jobs.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ import org.springframework.util.Assert;
|
||||
* Implementation of {@link JobDao} functionality based on the Hibernate ORM
|
||||
* framework. Its advantage is the independence of implementation on the
|
||||
* underlying database.
|
||||
*
|
||||
* @author tomas.slanina
|
||||
*
|
||||
* @author Tomas Slanina
|
||||
* @author Dave Syer
|
||||
*/
|
||||
|
||||
@@ -43,7 +43,7 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
|
||||
|
||||
/**
|
||||
* @see JobDao#createJob(JobIdentifier)
|
||||
*
|
||||
*
|
||||
* In this Hibernate implementation a job is stored into the database. Id is
|
||||
* obtained from Hibernate.
|
||||
*/
|
||||
@@ -62,7 +62,7 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
|
||||
|
||||
/**
|
||||
* @see JobDao#findJobs(JobIdentifier)
|
||||
*
|
||||
*
|
||||
* Hibernate is asked to get all jobs that matches criteria. Afterwards,
|
||||
* result is mapped into domain objects.
|
||||
*/
|
||||
@@ -109,7 +109,7 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
|
||||
|
||||
/**
|
||||
* @see JobDao#save(JobExecution)
|
||||
*
|
||||
*
|
||||
* Hibernate implementation persists JobExecution instance. Id is obtained
|
||||
* from Hibernate.
|
||||
*/
|
||||
@@ -168,7 +168,7 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
|
||||
public Object doInHibernate(Session session) {
|
||||
Criteria criteria = session
|
||||
.createCriteria(JobExecution.class);
|
||||
criteria.add(Expression.eq("jobId", jobId));
|
||||
criteria.add(Expression.eq("job.id", jobId));
|
||||
return criteria.list();
|
||||
}
|
||||
});
|
||||
@@ -179,7 +179,7 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
|
||||
/*
|
||||
* Validate JobExecution. At a minimum, JobId, StartTime, EndTime, and
|
||||
* Status cannot be null.
|
||||
*
|
||||
*
|
||||
* @param jobExecution @throws IllegalArgumentException
|
||||
*/
|
||||
private void validateJobExecution(JobExecution jobExecution) {
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.batch.restart.GenericRestartData;
|
||||
import org.springframework.batch.restart.RestartData;
|
||||
import org.springframework.batch.support.PropertiesConverter;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
@@ -41,18 +42,18 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Sql implementation of {@link StepDao}. Uses Sequences (via Spring's
|
||||
*
|
||||
*
|
||||
* @link DataFieldMaxValueIncrementer abstraction) to create all Step and
|
||||
* StepExecution primary keys before inserting a new row. All objects are
|
||||
* checked to ensure all fields to be stored are not null. If any are
|
||||
* found to be null, an IllegalArgumentException will be thrown. This
|
||||
* could be left to JdbcTemplate, however, the exception will be fairly
|
||||
* vague, and fails to highlight which field caused the exception.
|
||||
*
|
||||
*
|
||||
* TODO: JavaDoc should be geared more towards usability, the comments above are
|
||||
* useful information, and should be there, but needs usability stuff. Depends
|
||||
* on the step dao java docs as well.
|
||||
*
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @see StepDao
|
||||
*/
|
||||
@@ -97,7 +98,7 @@ public class SqlStepDao implements StepDao, InitializingBean {
|
||||
* Public setter for the table prefix property. This will be prefixed to all
|
||||
* the table names before queries are executed. Defaults to
|
||||
* {@value #DEFAULT_TABLE_PREFIX}.
|
||||
*
|
||||
*
|
||||
* @param tablePrefix
|
||||
* the tablePrefix to set
|
||||
*/
|
||||
@@ -121,11 +122,11 @@ public class SqlStepDao implements StepDao, InitializingBean {
|
||||
* row returned to a step object. If none are found, the list will be empty
|
||||
* and null will be returned. If one step is found, it will be returned. If
|
||||
* anymore than one step is found, an exception is thrown.
|
||||
*
|
||||
*
|
||||
* @see StepDao#findStep(Long, String)
|
||||
* @throws IllegalArgumentException
|
||||
* if job, stepName, or job.id is null.
|
||||
* @throws NoSuchBatchDomainObjectException
|
||||
* @throws IncorrectResultSizeDataAccessException
|
||||
* if more than one step is found.
|
||||
*/
|
||||
public StepInstance findStep(JobInstance job, String stepName) {
|
||||
@@ -162,19 +163,19 @@ public class SqlStepDao implements StepDao, InitializingBean {
|
||||
// This error will likely never be thrown, because there should
|
||||
// never be two steps with the same name and Job_ID due to database
|
||||
// constraints.
|
||||
throw new NoSuchBatchDomainObjectException(
|
||||
throw new IncorrectResultSizeDataAccessException(
|
||||
"Step Invalid, multiple steps found for StepName:"
|
||||
+ stepName + " and JobId:" + job.getId());
|
||||
+ stepName + " and JobId:" + job.getId(), 1, steps.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see StepDao#findSteps(JobInstance)
|
||||
*
|
||||
*
|
||||
* Sql implementation which uses a RowMapper to populate a list of all rows
|
||||
* in the step table with the same JOB_ID.
|
||||
*
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if jobId is null.
|
||||
*/
|
||||
@@ -205,7 +206,7 @@ public class SqlStepDao implements StepDao, InitializingBean {
|
||||
* Create a step with the given job's id, and the provided step name. A
|
||||
* unique id is created for the step using an incrementer. (@link
|
||||
* DataFieldMaxValueIncrementer)
|
||||
*
|
||||
*
|
||||
* @see StepDao#createStep(JobInstance, String)
|
||||
* @throws IllegalArgumentException
|
||||
* if job or stepName is null.
|
||||
@@ -251,7 +252,7 @@ public class SqlStepDao implements StepDao, InitializingBean {
|
||||
* Save a StepExecution. A unique id will be generated by the
|
||||
* stepExecutionIncrementor, and then set in the StepExecution. All values
|
||||
* will then be stored via an INSERT statement.
|
||||
*
|
||||
*
|
||||
* @see StepDao#save(StepExecution)
|
||||
*/
|
||||
public void save(StepExecution stepExecution) {
|
||||
@@ -333,12 +334,10 @@ public class SqlStepDao implements StepDao, InitializingBean {
|
||||
/**
|
||||
* Get StepExecution for the given step. Due to the nature of statistics,
|
||||
* they will not be returned with reconstituted object.
|
||||
*
|
||||
*
|
||||
* @see StepDao#getStepExecution(Long)
|
||||
* @throws IllegalArgumentException
|
||||
* if id is null.
|
||||
* @throws NoSuchBatchDomainObjectException
|
||||
* if more than one step execution is returned.
|
||||
*/
|
||||
public List findStepExecutions(final StepInstance step) {
|
||||
|
||||
@@ -400,7 +399,7 @@ public class SqlStepDao implements StepDao, InitializingBean {
|
||||
/*
|
||||
* Validate StepExecution. At a minimum, JobId, StartTime, and Status cannot
|
||||
* be null. EndTime can be null for an unfinished job.
|
||||
*
|
||||
*
|
||||
* @param jobExecution @throws IllegalArgumentException
|
||||
*/
|
||||
private void validateStepExecution(StepExecution stepExecution) {
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.batch.core.tasklet.Tasklet;
|
||||
import org.springframework.batch.execution.repository.dao.JobDao;
|
||||
import org.springframework.batch.execution.repository.dao.StepDao;
|
||||
import org.springframework.batch.restart.GenericRestartData;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
|
||||
/*
|
||||
* Test SimpleJobRepository. The majority of test cases are tested using EasyMock,
|
||||
@@ -176,7 +177,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
try{
|
||||
jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
|
||||
fail();
|
||||
}catch(BatchRestartException ex){
|
||||
}catch(IncorrectResultSizeDataAccessException ex){
|
||||
//expected
|
||||
}
|
||||
|
||||
@@ -273,7 +274,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testSaveOrUpdateValidJobExecution() throws Exception {
|
||||
|
||||
JobExecution jobExecution = new JobExecution(new JobInstance(null, new Long(1)));
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractJobDaoTests extends
|
||||
AbstractTransactionalDataSourceSpringContextTests {
|
||||
@@ -170,15 +170,15 @@ public abstract class AbstractJobDaoTests extends
|
||||
jobExecution.setEndTime(new Timestamp(System.currentTimeMillis()));
|
||||
jobDao.update(jobExecution);
|
||||
|
||||
List executions = retrieveJobExecution(jobExecution.getId());
|
||||
List executions = jobDao.findJobExecutions(job);
|
||||
assertEquals(executions.size(), 1);
|
||||
validateJobExecution(jobExecution, (JobExecution) executions.get(0));
|
||||
|
||||
}
|
||||
|
||||
public void testSaveJobExecution() {
|
||||
public void testSaveJobExecution(){
|
||||
|
||||
List executions = retrieveJobExecution(jobExecution.getId());
|
||||
List executions = jobDao.findJobExecutions(job);
|
||||
assertEquals(executions.size(), 1);
|
||||
validateJobExecution(jobExecution, (JobExecution) executions.get(0));
|
||||
}
|
||||
@@ -243,9 +243,16 @@ public abstract class AbstractJobDaoTests extends
|
||||
|
||||
}
|
||||
|
||||
private void validateJobExecution(JobExecution lhs, JobExecution rhs) {
|
||||
public void testFindJobExecutions(){
|
||||
|
||||
// equals operator only checks id
|
||||
List results = jobDao.findJobExecutions(job);
|
||||
assertEquals(results.size(), 1);
|
||||
validateJobExecution(jobExecution, (JobExecution)results.get(0));
|
||||
}
|
||||
|
||||
private void validateJobExecution(JobExecution lhs, JobExecution rhs){
|
||||
|
||||
//equals operator only checks id
|
||||
assertEquals(lhs, rhs);
|
||||
assertEquals(lhs.getStartTime(), rhs.getStartTime());
|
||||
assertEquals(lhs.getEndTime(), rhs.getEndTime());
|
||||
@@ -253,27 +260,4 @@ public abstract class AbstractJobDaoTests extends
|
||||
assertEquals(lhs.getExitStatus(), rhs.getExitStatus());
|
||||
}
|
||||
|
||||
private List retrieveJobExecution(final Long id) {
|
||||
|
||||
RowMapper rowMapper = new RowMapper() {
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
|
||||
JobExecution execution = new JobExecution(new JobInstance(
|
||||
jobRuntimeInformation, new Long(rs.getLong(1))));
|
||||
execution.setStartTime(rs.getTimestamp(2));
|
||||
execution.setEndTime(rs.getTimestamp(3));
|
||||
execution.setStatus(BatchStatus.getStatus(rs.getString(4)));
|
||||
// TODO: Add boolean for continuable to queries
|
||||
execution.setExitStatus(new ExitStatus("Y".equals(rs
|
||||
.getString(5)), rs.getString(6), rs.getString(7)));
|
||||
execution.setId(id);
|
||||
|
||||
return execution;
|
||||
}
|
||||
};
|
||||
|
||||
return jdbcTemplate.query(GET_JOB_EXECUTION, new Object[] { id },
|
||||
rowMapper);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,11 +26,13 @@ import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.core.domain.StepInstance;
|
||||
import org.springframework.batch.core.executor.ExitCodeExceptionClassifier;
|
||||
import org.springframework.batch.core.repository.NoSuchBatchDomainObjectException;
|
||||
import org.springframework.batch.core.runtime.JobIdentifier;
|
||||
import org.springframework.batch.execution.runtime.ScheduledJobIdentifier;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.batch.restart.GenericRestartData;
|
||||
import org.springframework.batch.restart.RestartData;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -38,7 +40,7 @@ import org.springframework.util.ClassUtils;
|
||||
* Test for StepDao. Because it is very reasonable to assume that there is a
|
||||
* foreign key constraint on the JobId of a step, the JobDao is used to create
|
||||
* jobs, to have an id for creating steps.
|
||||
*
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@@ -49,11 +51,11 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour
|
||||
protected StepDao stepDao;
|
||||
|
||||
protected JobInstance job;
|
||||
|
||||
|
||||
protected StepInstance step1;
|
||||
|
||||
|
||||
protected StepInstance step2;
|
||||
|
||||
|
||||
protected StepExecution stepExecution;
|
||||
|
||||
protected JobExecution jobExecution;
|
||||
@@ -90,29 +92,40 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour
|
||||
stepExecution.setStartTime(new Timestamp(System.currentTimeMillis()));
|
||||
stepDao.save(stepExecution);
|
||||
}
|
||||
|
||||
|
||||
public void testVersionIsNotNullForStep() throws Exception {
|
||||
int version = jdbcTemplate.queryForInt("select version from BATCH_STEP where ID="+step1.getId());
|
||||
assertEquals(0, version);
|
||||
}
|
||||
|
||||
|
||||
public void testVersionIsNotNullForStepExecution() throws Exception {
|
||||
int version = jdbcTemplate.queryForInt("select version from BATCH_STEP_EXECUTION where ID="+stepExecution.getId());
|
||||
assertEquals(0, version);
|
||||
}
|
||||
|
||||
|
||||
public void testFindStepNull(){
|
||||
|
||||
|
||||
StepInstance step = stepDao.findStep(job, "UnSavedStep");
|
||||
assertNull(step);
|
||||
}
|
||||
|
||||
|
||||
public void testFindStep(){
|
||||
|
||||
|
||||
StepInstance tempStep = stepDao.findStep(job, "TestStep1");
|
||||
assertEquals(tempStep, step1);
|
||||
}
|
||||
|
||||
|
||||
public void testFindStepsWithSameId(){
|
||||
StepInstance duplicateStep = new StepInstance(step1.getId());
|
||||
stepDao.createStep(job, step1.getName());
|
||||
try{
|
||||
stepDao.findStep(job, step1.getName());
|
||||
fail();
|
||||
}catch(IncorrectResultSizeDataAccessException ex){
|
||||
//expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testFindSteps(){
|
||||
|
||||
List steps = stepDao.findSteps(job);
|
||||
@@ -120,31 +133,31 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour
|
||||
assertTrue(steps.contains(step1));
|
||||
assertTrue(steps.contains(step2));
|
||||
}
|
||||
|
||||
|
||||
public void testFindStepsNotSaved(){
|
||||
|
||||
|
||||
//no steps are saved for given id, empty list should be returned
|
||||
List steps = stepDao.findSteps(new JobInstance(null, new Long(38922)));
|
||||
assertEquals(steps.size(), 0);
|
||||
}
|
||||
|
||||
|
||||
public void testCreateStep(){
|
||||
|
||||
|
||||
StepInstance step3 = stepDao.createStep(job, "TestStep3");
|
||||
StepInstance tempStep = stepDao.findStep(job, "TestStep3");
|
||||
assertEquals(step3, tempStep);
|
||||
}
|
||||
|
||||
|
||||
public void testUpdateStepWithoutRestartData(){
|
||||
|
||||
|
||||
step1.setStatus(BatchStatus.COMPLETED);
|
||||
stepDao.update(step1);
|
||||
StepInstance tempStep = stepDao.findStep(job, step1.getName());
|
||||
assertEquals(tempStep, step1);
|
||||
}
|
||||
|
||||
|
||||
public void testUpdateStepWithRestartData(){
|
||||
|
||||
|
||||
step1.setStatus(BatchStatus.COMPLETED);
|
||||
Properties data = new Properties();
|
||||
data.setProperty("restart.key1", "restartData");
|
||||
@@ -153,10 +166,10 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour
|
||||
stepDao.update(step1);
|
||||
StepInstance tempStep = stepDao.findStep(job, step1.getName());
|
||||
assertEquals(tempStep, step1);
|
||||
assertEquals(tempStep.getRestartData().getProperties().toString(),
|
||||
assertEquals(tempStep.getRestartData().getProperties().toString(),
|
||||
restartData.getProperties().toString());
|
||||
}
|
||||
|
||||
|
||||
public void testSaveStepExecution(){
|
||||
|
||||
StepExecution execution = new StepExecution(step2, jobExecution);
|
||||
@@ -175,9 +188,9 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour
|
||||
assertEquals(execution.getStatistics(), tempExecution.getStatistics());
|
||||
assertEquals(execution.getExitStatus(), tempExecution.getExitStatus());
|
||||
}
|
||||
|
||||
|
||||
public void testUpdateStepExecution(){
|
||||
|
||||
|
||||
stepExecution.setStatus(BatchStatus.COMPLETED);
|
||||
stepExecution.setEndTime(new Timestamp(System.currentTimeMillis()));
|
||||
stepExecution.setCommitCount(5);
|
||||
@@ -191,7 +204,7 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour
|
||||
assertEquals(stepExecution, tempExecution);
|
||||
assertEquals(stepExecution.getExitStatus(), tempExecution.getExitStatus());
|
||||
}
|
||||
|
||||
|
||||
public void testUpdateStepExecutionWithNullId(){
|
||||
StepExecution stepExecution = new StepExecution(null, null);
|
||||
try{
|
||||
@@ -201,15 +214,15 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour
|
||||
//expected
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testGetStepExecutionCountForNoExecutions(){
|
||||
|
||||
|
||||
int executionCount = stepDao.getStepExecutionCount(step2.getId());
|
||||
assertEquals(executionCount, 0);
|
||||
}
|
||||
|
||||
public void testIncrementStepExecutionCount(){
|
||||
|
||||
|
||||
assertEquals(1, stepDao.getStepExecutionCount(step1.getId()));
|
||||
StepExecution execution = new StepExecution(step1, new JobExecution(step1.getJob(), new Long(123)));
|
||||
stepDao.save(execution);
|
||||
|
||||
Reference in New Issue
Block a user