BATCH-677: tidied up some loose ends with BatchStatus (e.g. PAUSED->WAITING).

This commit is contained in:
dsyer
2008-11-17 14:34:44 +00:00
parent df3b9181e3
commit 1cf7cdad54
22 changed files with 308 additions and 76 deletions

View File

@@ -26,21 +26,82 @@ package org.springframework.batch.core;
public enum BatchStatus {
/**
* The order of the status values is significant. An execution is expected
* to move up from lowest to highest, hopefully stopping at COMPLETED. After
* COMPLETED, higher values signify more serious failure.
* The order of the status values is significant because it can be used to
* aggregate a set of status values - the result should be the maximum
* value. Since COMPLETED is first in the order, only if all elements of an
* execution are COMPLETED will the aggregate status be COMPLETED. A running
* execution is expected to move from STARTING to STARTED to COMPLETED
* (through the order defined by {@link #upgradeTo(BatchStatus)}). Higher
* values than STARTED signify more serious failure.
*/
STARTING, STARTED, COMPLETED, PAUSED, FAILED, STOPPING, STOPPED, UNKNOWN;
COMPLETED, STARTING, WAITING, STARTED, FAILED, STOPPING, STOPPED, UNKNOWN;
public static BatchStatus max(BatchStatus status1, BatchStatus status2) {
if (status1.compareTo(status2) < 0) {
if (status1.isLessThan(status2)) {
return status2;
}
if (status1.compareTo(status2) > 0) {
if (status1.isGreaterThan(status2)) {
return status1;
}
else
return status1;
}
/**
* Convenience method to decide if a status indicates work is in progress.
*
* @return true if the status is STARTING, STARTED or WAITING
*/
public boolean isRunning() {
return this == STARTING || this == STARTED || this == WAITING;
}
/**
* Convenience method to decide if a status indicates execution was unsuccessful.
*
* @return true if the status is FAILED or greater
*/
public boolean isUnsuccessful() {
return this==FAILED || this.isGreaterThan(FAILED);
}
/**
* Method used to move status values through their logical progression, and
* override less severe failures with more severe ones. This value is
* compared with the parameter and the one that has higher priority is
* returned. If both are STARTED or less than the value returned is the
* largest in the sequence STARTING, STARTED, COMPLETED. Otherwise the value
* returned is the maximum of the two.
*
* @param other another status to compare to
* @return either this or the other status depending on their priority
*/
public BatchStatus upgradeTo(BatchStatus other) {
if (isGreaterThan(STARTED) || other.isGreaterThan(STARTED)) {
return max(this, other);
}
// Both less than or equal to STARTED
if (this == COMPLETED)
return COMPLETED;
if (other == COMPLETED)
return COMPLETED;
return max(this, other);
}
/**
* @param other a status value to compare
* @return true if this is greater than other
*/
public boolean isGreaterThan(BatchStatus other) {
return this.compareTo(other) > 0;
}
/**
* @param other a status value to compare
* @return true if this is less than other
*/
public boolean isLessThan(BatchStatus other) {
return this.compareTo(other) < 0;
}
}

View File

@@ -121,9 +121,7 @@ public class JobExecution extends Entity {
* @param status the new status value
*/
public void upgradeStatus(BatchStatus status) {
if (status.compareTo(this.status) > 0) {
this.status = status;
}
this.status = this.status.upgradeTo(status);
}
/**
@@ -211,23 +209,26 @@ public class JobExecution extends Entity {
}
/**
* Signal that this job execution wishes to be paused. Uses
* {@link #upgradeStatus(BatchStatus)} so that a failed execution stays
* failed.
* Signal that this job execution wishes to wait for work to complete, and
* no more processing will take place on the current thread. A failed
* execution stays failed.
*/
public void pause() {
upgradeStatus(BatchStatus.PAUSED);
public void pauseAndWait() {
if (!status.isUnsuccessful()) {
status = BatchStatus.WAITING;
}
}
/**
* Test if the {@link JobExecution} has been paused.
* Test if the {@link JobExecution} has been paused and is waiting for work
* to be done.
*
* @see #pause()
* @see #pauseAndWait()
*
* @return true if this instance is paused
* @return true if this instance is waiting
*/
public boolean isPaused() {
return status == BatchStatus.PAUSED;
public boolean isWaiting() {
return status == BatchStatus.WAITING;
}
/**

View File

@@ -53,7 +53,7 @@ public class StepExecution extends Entity {
private volatile int rollbackCount = 0;
private volatile int readSkipCount = 0;
private volatile int processSkipCount = 0;
private volatile int writeSkipCount = 0;
@@ -71,7 +71,7 @@ public class StepExecution extends Entity {
private volatile boolean terminateOnly;
private volatile int filterCount;
private transient volatile List<Throwable> failureExceptions = new ArrayList<Throwable>();
/**
@@ -155,7 +155,7 @@ public class StepExecution extends Entity {
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
/**
* Returns the current number of items read for this execution
*
@@ -209,10 +209,11 @@ public class StepExecution extends Entity {
public int getFilterCount() {
return filterCount;
}
/**
* Public setter for the number of items filtered out of this execution.
* @param filterCount the number of items filtered out of this execution to set
* @param filterCount the number of items filtered out of this execution to
* set
*/
public void setFilterCount(int filterCount) {
this.filterCount = filterCount;
@@ -261,6 +262,40 @@ public class StepExecution extends Entity {
this.status = status;
}
/**
* Upgrade the status field if the provided value is greater than the
* existing one. Clients using this method to set the status can be sure
* that they don't overwrite a failed status with an successful one.
*
* @param status the new status value
*/
public void upgradeStatus(BatchStatus status) {
this.status = this.status.upgradeTo(status);
}
/**
* Signal that this job execution wishes to wait for work to complete, and
* no more processing will take place on the current thread. A failed
* execution stays failed.
*/
public void pauseAndWait() {
if (!status.isUnsuccessful()) {
status = BatchStatus.WAITING;
}
}
/**
* Test if the {@link JobExecution} has been paused and is waiting for work
* to be done.
*
* @see #pauseAndWait()
*
* @return true if this instance is waiting
*/
public boolean isWaiting() {
return status == BatchStatus.WAITING;
}
/**
* @return the name of the step
*/
@@ -410,7 +445,7 @@ public class StepExecution extends Entity {
public void setWriteSkipCount(int writeSkipCount) {
this.writeSkipCount = writeSkipCount;
}
/**
* @return the number of records skipped during processing
*/
@@ -442,12 +477,12 @@ public class StepExecution extends Entity {
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
public List<Throwable> getFailureExceptions() {
return failureExceptions;
}
public void addFailureException(Throwable throwable){
public void addFailureException(Throwable throwable) {
this.failureExceptions.add(throwable);
}
@@ -470,7 +505,8 @@ public class StepExecution extends Entity {
}
/**
* Deserialise and ensure transient fields are re-instantiated when read back
* Deserialise and ensure transient fields are re-instantiated when read
* back
*/
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
@@ -490,9 +526,10 @@ public class StepExecution extends Entity {
public String toString() {
return super.toString()
+ String.format(", name=%s, status=%s, exitStatus=%s, readCount=%d, filterCount=%d, writeCount=%d readSkipCount=%d, writeSkipCount=%d"
+ ", commitCount=%d, rollbackCount=%d", stepName, status, exitStatus, readCount, filterCount, writeCount, readSkipCount, writeSkipCount,
commitCount, rollbackCount);
+ String.format(
", name=%s, status=%s, exitStatus=%s, readCount=%d, filterCount=%d, writeCount=%d readSkipCount=%d, writeSkipCount=%d"
+ ", commitCount=%d, rollbackCount=%d", stepName, status, exitStatus, readCount,
filterCount, writeCount, readSkipCount, writeSkipCount, commitCount, rollbackCount);
}
}

View File

@@ -99,7 +99,7 @@ public class SimpleJobExplorer implements JobExplorer {
* @see org.springframework.batch.core.explore.JobExplorer#getStepExecution(java.lang.Long)
*/
public StepExecution getStepExecution(Long executionId, String stepName) {
JobExecution jobExecution = jobExecutionDao.getJobExecution(executionId);
JobExecution jobExecution = getJobExecution(executionId);
return stepExecutionDao.getStepExecution(jobExecution, stepName);
}

View File

@@ -219,7 +219,7 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea
execution.setStartTime(new Date());
// If paused we need to retain the status so that subclasses can
// handle the resume, otherwise we mark it as started...
if (!execution.isPaused()) {
if (!execution.isWaiting()) {
updateStatus(execution, BatchStatus.STARTED);
}
@@ -228,7 +228,7 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea
StepExecution lastStepExecution = doExecute(execution);
if (lastStepExecution != null) {
if (!execution.isPaused()) {
if (!execution.isWaiting()) {
// If the subclass wants to pause don't change the
// status.
execution.setStatus(lastStepExecution.getStatus());
@@ -247,13 +247,13 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea
}
catch (JobInterruptedException e) {
logger.error(e);
logger.error("Encountered interruption executing job", e);
execution.setExitStatus(ExitStatus.FAILED);
execution.setStatus(BatchStatus.STOPPED);
execution.addFailureException(e);
}
catch (Throwable t) {
logger.error(t);
logger.error("Encountered error executing job", t);
execution.setExitStatus(ExitStatus.FAILED);
execution.setStatus(BatchStatus.FAILED);
execution.addFailureException(t);
@@ -307,14 +307,13 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea
JobInstance jobInstance = execution.getJobInstance();
StepExecution currentStepExecution = null;
StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step.getName());
StepExecution currentStepExecution = lastStepExecution;
if (shouldStart(jobInstance, step)) {
if (shouldStart(lastStepExecution, jobInstance, step)) {
currentStepExecution = execution.createStepExecution(step.getName());
StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step.getName());
boolean isRestart = (lastStepExecution != null && !lastStepExecution.getStatus().equals(
BatchStatus.COMPLETED)) ? true : false;
@@ -343,18 +342,19 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea
/**
* Given a step and configuration, return true if the step should start,
* false if it should not, and throw an exception if the job should finish.
* @param lastStepExecution the last step execution
* @param jobInstance
* @param step
*
* @throws StartLimitExceededException if the start limit has been exceeded
* for this step
* @throws JobRestartException if the job is in an inconsistent state from
* an earlier failure
*/
private boolean shouldStart(JobInstance jobInstance, Step step) throws JobRestartException,
private boolean shouldStart(StepExecution lastStepExecution, JobInstance jobInstance, Step step) throws JobRestartException,
StartLimitExceededException {
BatchStatus stepStatus;
// if the last execution is null, the step has never been executed.
StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step.getName());
if (lastStepExecution == null) {
stepStatus = BatchStatus.STARTING;
}

View File

@@ -27,8 +27,8 @@ public class PauseState extends AbstractState {
// not already paused we pause it, and expect the flow to respect the
// status.
synchronized (jobExecution) {
if (!jobExecution.isPaused()) {
jobExecution.pause();
if (!jobExecution.isWaiting()) {
jobExecution.pauseAndWait();
return FlowExecution.PAUSED;
}

View File

@@ -84,7 +84,7 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean {
final JobExecution jobExecution;
JobExecution lastExecution = jobRepository.getLastJobExecution(job.getName(), jobParameters);
if (lastExecution != null) {
if (lastExecution.isPaused()) {
if (lastExecution.isWaiting()) {
jobExecution = lastExecution;
// this execution will be continued => delete the end time
jobExecution.setEndTime(null);

View File

@@ -370,7 +370,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean {
public boolean pause(long executionId) throws NoSuchJobExecutionException {
JobExecution jobExecution = findExecutionById(executionId);
jobExecution.pause();
jobExecution.pauseAndWait();
jobRepository.update(jobExecution);
return true;
}

View File

@@ -73,15 +73,16 @@ public class PartitionStep extends AbstractStep {
// Wait for task completion and then aggregate the results
Collection<StepExecution> executions = partitionHandler.handle(stepExecutionSplitter, stepExecution);
stepExecution.upgradeStatus(BatchStatus.COMPLETED);
aggregator.aggregate(stepExecution, executions);
if (stepExecution.getJobExecution().isPaused()) {
return;
}
// If anything failed or had a problem we need to crap out
if (stepExecution.getStatus().isUnsuccessful()) {
throw new JobExecutionException("Partition handler returned an unsuccessful step");
}
if (stepExecution.getStatus() != BatchStatus.COMPLETED) {
throw new JobExecutionException("Partition handler returned an incomplete step");
stepExecution.pauseAndWait();
}
}

View File

@@ -191,7 +191,7 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
if (count == 0) {
int curentVersion = getJdbcTemplate().queryForInt(getQuery(CURRENT_VERSION_JOB_EXECUTION),
new Object[] { jobExecution.getId() });
throw new OptimisticLockingFailureException("Attempt to update step execution id="
throw new OptimisticLockingFailureException("Attempt to update job execution id="
+ jobExecution.getId() + " with wrong version (" + jobExecution.getVersion()
+ "), where current version is " + curentVersion);
}

View File

@@ -199,6 +199,7 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
}
stepExecution.setStatus(BatchStatus.COMPLETED);
logger.debug("Step execution success: " + stepExecution);
try {
getJobRepository().update(stepExecution);
@@ -265,6 +266,9 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
+ "This job is now in an unknown state and should not be restarted.", commitException);
stepExecution.addFailureException(commitException);
}
logger.debug("Step execution complete: " + stepExecution);
}
}

View File

@@ -44,6 +44,42 @@ public class BatchStatusTests {
assertEquals(BatchStatus.FAILED, BatchStatus.max(BatchStatus.FAILED,BatchStatus.COMPLETED));
assertEquals(BatchStatus.FAILED, BatchStatus.max(BatchStatus.COMPLETED, BatchStatus.FAILED));
assertEquals(BatchStatus.FAILED, BatchStatus.max(BatchStatus.FAILED, BatchStatus.FAILED));
assertEquals(BatchStatus.STARTED, BatchStatus.max(BatchStatus.STARTED, BatchStatus.STARTING));
assertEquals(BatchStatus.STARTED, BatchStatus.max(BatchStatus.COMPLETED, BatchStatus.STARTED));
}
@Test
public void testUpgradeStatusFinished() {
assertEquals(BatchStatus.FAILED, BatchStatus.FAILED.upgradeTo(BatchStatus.COMPLETED));
assertEquals(BatchStatus.FAILED, BatchStatus.COMPLETED.upgradeTo(BatchStatus.FAILED));
}
@Test
public void testUpgradeStatusUnfinished() {
assertEquals(BatchStatus.COMPLETED, BatchStatus.STARTING.upgradeTo(BatchStatus.COMPLETED));
assertEquals(BatchStatus.COMPLETED, BatchStatus.COMPLETED.upgradeTo(BatchStatus.STARTING));
assertEquals(BatchStatus.STARTED, BatchStatus.STARTING.upgradeTo(BatchStatus.STARTED));
assertEquals(BatchStatus.STARTED, BatchStatus.STARTED.upgradeTo(BatchStatus.STARTING));
assertEquals(BatchStatus.COMPLETED, BatchStatus.COMPLETED.upgradeTo(BatchStatus.WAITING));
assertEquals(BatchStatus.STARTED, BatchStatus.STARTED.upgradeTo(BatchStatus.WAITING));
}
@Test
public void testIsRunning() {
assertFalse(BatchStatus.FAILED.isRunning());
assertFalse(BatchStatus.COMPLETED.isRunning());
assertTrue(BatchStatus.STARTED.isRunning());
assertTrue(BatchStatus.STARTING.isRunning());
assertTrue(BatchStatus.WAITING.isRunning());
}
@Test
public void testIsUnsuccessful() {
assertTrue(BatchStatus.FAILED.isUnsuccessful());
assertFalse(BatchStatus.COMPLETED.isUnsuccessful());
assertFalse(BatchStatus.STARTED.isUnsuccessful());
assertFalse(BatchStatus.STARTING.isUnsuccessful());
assertFalse(BatchStatus.WAITING.isUnsuccessful());
}
@Test

View File

@@ -109,12 +109,34 @@ public class JobExecutionTests {
/**
* Test method for
* {@link org.springframework.batch.core.JobExecution#pause()}.
* {@link org.springframework.batch.core.JobExecution#pauseAndWait()}.
*/
@Test
public void testPause() {
execution.pause();
assertEquals(BatchStatus.PAUSED, execution.getStatus());
public void testPauseAndWait() {
execution.pauseAndWait();
assertEquals(BatchStatus.WAITING, execution.getStatus());
}
/**
* Test method for
* {@link org.springframework.batch.core.JobExecution#pauseAndWait()}.
*/
@Test
public void testPauseAndWaitWhenFailed() {
execution.setStatus(BatchStatus.FAILED);
execution.pauseAndWait();
assertEquals(BatchStatus.FAILED, execution.getStatus());
}
/**
* Test method for
* {@link org.springframework.batch.core.JobExecution#pauseAndWait()}.
*/
@Test
public void testPauseAndWaitWhenStarted() {
execution.setStatus(BatchStatus.STARTED);
execution.pauseAndWait();
assertEquals(BatchStatus.WAITING, execution.getStatus());
}
/**

View File

@@ -275,6 +275,49 @@ public class StepExecutionTests {
assertEquals(exception, execution.getFailureExceptions().get(0));
}
/**
* Test method for
* {@link org.springframework.batch.core.JobExecution#pauseAndWait()}.
*/
@Test
public void testPauseAndWait() {
execution.pauseAndWait();
assertEquals(BatchStatus.WAITING, execution.getStatus());
}
/**
* Test method for
* {@link org.springframework.batch.core.JobExecution#pauseAndWait()}.
*/
@Test
public void testPauseAndWaitWhenFailed() {
execution.setStatus(BatchStatus.FAILED);
execution.pauseAndWait();
assertEquals(BatchStatus.FAILED, execution.getStatus());
}
/**
* Test method for
* {@link org.springframework.batch.core.JobExecution#pauseAndWait()}.
*/
@Test
public void testPauseAndWaitWhenStarted() {
execution.setStatus(BatchStatus.STARTED);
execution.pauseAndWait();
assertEquals(BatchStatus.WAITING, execution.getStatus());
}
/**
* Test method for
* {@link org.springframework.batch.core.JobExecution#getStatus()}.
*/
@Test
public void testDowngradeStatus() {
execution.setStatus(BatchStatus.FAILED);
execution.upgradeStatus(BatchStatus.COMPLETED);
assertEquals(BatchStatus.FAILED, execution.getStatus());
}
private StepExecution newStepExecution(Step step, Long long2) {
JobInstance job = new JobInstance(new Long(3), new JobParameters(), "testJob");
StepExecution execution = new StepExecution(step.getName(), new JobExecution(job, long2), new Long(4));

View File

@@ -76,6 +76,7 @@ public class SimpleJobExplorerTests extends TestCase {
public void testGetStepExecution() throws Exception {
expect(jobExecutionDao.getJobExecution(123L)).andReturn(jobExecution);
expect(stepExecutionDao.getStepExecution(jobExecution, "foo")).andReturn(null);
expect(stepExecutionDao.getStepExecutions(jobExecution)).andReturn(null);
replay(jobExecutionDao, stepExecutionDao);
jobExplorer.getStepExecution(123L,"foo");
verify(jobExecutionDao, stepExecutionDao);

View File

@@ -313,6 +313,16 @@ public class SimpleJobTests {
ex.getMessage().indexOf("start limit exceeded") >= 0);
}
@Test
public void testStepAlreadyComplete() throws Exception {
stepExecution1.setStatus(BatchStatus.COMPLETED);
jobRepository.add(stepExecution1);
job.execute(jobExecution);
assertEquals(0, jobExecution.getFailureExceptions().size());
assertEquals(1, jobExecution.getStepExecutions().size());
assertEquals(stepExecution2.getStepName(), jobExecution.getStepExecutions().iterator().next().getStepName());
}
@Test
public void testNoSteps() throws Exception {
job.setSteps(new ArrayList<Step>());

View File

@@ -265,7 +265,7 @@ public class FlowJobTests {
if (!jobExecution.getAllFailureExceptions().isEmpty()) {
throw jobExecution.getAllFailureExceptions().get(0);
}
assertEquals(BatchStatus.PAUSED, jobExecution.getStatus());
assertEquals(BatchStatus.WAITING, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
job.execute(jobExecution);

View File

@@ -194,7 +194,7 @@ public class SimpleJobLauncherTests {
public void testResumePausedInstance() throws Exception {
long id = 9;
JobExecution jobExecution = new JobExecution(null, id);
jobExecution.pause();
jobExecution.pauseAndWait();
expect(jobRepository.getLastJobExecution(job.getName(), jobParameters)).andReturn(jobExecution);
replay(jobRepository);

View File

@@ -402,7 +402,7 @@ public class SimpleJobOperatorTests {
jobOperator.pause(111L);
verify(jobExplorer);
verify(jobRepository);
assertEquals(BatchStatus.PAUSED, jobExecution.getStatus());
assertEquals(BatchStatus.WAITING, jobExecution.getStatus());
}
}

View File

@@ -40,7 +40,7 @@ public class StepExecutionAggregatorTests {
stepExecution2.setStatus(BatchStatus.COMPLETED);
aggregator.aggregate(result, Arrays.<StepExecution> asList(stepExecution1, stepExecution2));
assertNotNull(result);
assertEquals(BatchStatus.COMPLETED, result.getStatus());
assertEquals(BatchStatus.STARTING, result.getStatus());
}
@Test

View File

@@ -224,6 +224,7 @@ public abstract class AbstractJobExecutionDaoTests extends AbstractTransactional
JobExecution value = dao.getJobExecution(exec.getId());
assertEquals(exec, value);
// N.B. the job instance is not re-hydrated in the JDBC case...
}
/**

View File

@@ -77,9 +77,10 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
dao = getStepExecutionDao();
}
@Transactional @Test
@Transactional
@Test
public void testSaveExecutionAssignsIdAndVersion() throws Exception {
assertNull(stepExecution.getId());
assertNull(stepExecution.getVersion());
dao.saveStepExecution(stepExecution);
@@ -87,9 +88,10 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
assertNotNull(stepExecution.getVersion());
}
@Transactional @Test
@Transactional
@Test
public void testSaveAndGetExecution() {
stepExecution.setStatus(BatchStatus.STARTED);
stepExecution.setReadSkipCount(7);
stepExecution.setWriteSkipCount(5);
@@ -102,18 +104,26 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
dao.saveStepExecution(stepExecution);
StepExecution retrieved = dao.getStepExecution(jobExecution, step.getName());
assertStepExecutionsAreEqual(stepExecution, retrieved);
assertNotNull(retrieved.getVersion());
assertNotNull(retrieved.getJobExecution());
assertNotNull(retrieved.getJobExecution().getId());
assertNotNull(retrieved.getJobExecution().getJobId());
assertNotNull(retrieved.getJobExecution().getJobInstance());
}
@Transactional
@Test
public void testSaveAndGetNonExistentExecution() {
assertNull(dao.getStepExecution(jobExecution, "not-existing step"));
}
@Transactional @Test
@Transactional
@Test
public void testSaveAndFindExecution() {
stepExecution.setStatus(BatchStatus.STARTED);
stepExecution.setReadSkipCount(7);
stepExecution.setWriteSkipCount(5);
@@ -124,7 +134,8 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
assertStepExecutionsAreEqual(stepExecution, retrieved.get(0));
}
@Transactional @Test
@Transactional
@Test
public void testGetForNotExistingJobExecution() {
assertNull(dao.getStepExecution(new JobExecution(jobInstance, (long) 777), step.getName()));
}
@@ -132,7 +143,8 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
/**
* To-be-saved execution must not already have an id.
*/
@Transactional @Test
@Transactional
@Test
public void testSaveExecutionWithIdAlreadySet() {
stepExecution.setId((long) 7);
try {
@@ -147,7 +159,8 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
/**
* To-be-saved execution must not already have a version.
*/
@Transactional @Test
@Transactional
@Test
public void testSaveExecutionWithVersionAlreadySet() {
stepExecution.incrementVersion();
try {
@@ -163,7 +176,8 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
* Update and retrieve updated StepExecution - make sure the update is
* reflected as expected and version number has been incremented
*/
@Transactional @Test
@Transactional
@Test
public void testUpdateExecution() {
stepExecution.setStatus(BatchStatus.STARTED);
dao.saveStepExecution(stepExecution);
@@ -184,7 +198,8 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
* Exception should be raised when the version of update argument doesn't
* match the version of persisted entity.
*/
@Transactional @Test
@Transactional
@Test
public void testConcurrentModificationException() {
step = new StepSupport("foo");
@@ -210,7 +225,7 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
}
}
private void assertStepExecutionsAreEqual(StepExecution expected, StepExecution actual) {
assertEquals(expected.getId(), actual.getId());
assertEquals(expected.getStartTime(), actual.getStartTime());