IN PROGRESS - issue BATCH-127: Allow job configuration to control re-entrant behavior
http://opensource.atlassian.com/projects/spring/browse/BATCH-127 Refactor JobRepository.findOrCreateJob() to return JobExecution.
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.batch.execution.launch;
|
||||
|
||||
import org.springframework.batch.core.executor.JobExecutionException;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JobExecutionAlreadyRunningException extends JobExecutionException {
|
||||
|
||||
/**
|
||||
* @param msg
|
||||
*/
|
||||
public JobExecutionAlreadyRunningException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param msg
|
||||
* @param cause
|
||||
*/
|
||||
public JobExecutionAlreadyRunningException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.springframework.batch.execution.launch;
|
||||
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobIdentifier;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
|
||||
/**
|
||||
* Interface which defines a facade for running jobs. The interface is
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.batch.execution.launch;
|
||||
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobIdentifier;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
|
||||
/**
|
||||
* Simple interface for controlling jobs, including possible ad-hoc executions,
|
||||
|
||||
@@ -29,8 +29,8 @@ import org.springframework.batch.core.configuration.JobConfigurationLocator;
|
||||
import org.springframework.batch.core.configuration.NoSuchJobConfigurationException;
|
||||
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.executor.JobExecutor;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.execution.job.DefaultJobExecutor;
|
||||
import org.springframework.batch.repeat.RepeatContext;
|
||||
@@ -164,15 +164,9 @@ class SimpleJobExecutorFacade implements JobExecutorFacade,
|
||||
JobConfiguration jobConfiguration = jobConfigurationLocator
|
||||
.getJobConfiguration(jobIdentifier.getName());
|
||||
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration,
|
||||
return jobRepository.findOrCreateJob(jobConfiguration,
|
||||
jobIdentifier);
|
||||
JobExecution execution = job.createNewJobExecution();
|
||||
|
||||
// Save the JobExecution so that it picks up an ID (useful for clients
|
||||
// monitoring asynchronous executions):
|
||||
jobRepository.saveOrUpdate(execution);
|
||||
|
||||
return execution;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.batch.core.configuration.NoSuchJobConfigurationExcept
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobIdentifier;
|
||||
import org.springframework.batch.core.executor.JobExecutor;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.runtime.JobIdentifierFactory;
|
||||
import org.springframework.batch.execution.job.DefaultJobExecutor;
|
||||
|
||||
@@ -29,6 +29,7 @@ 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.repository.BatchRestartException;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.execution.repository.dao.JobDao;
|
||||
import org.springframework.batch.execution.repository.dao.StepDao;
|
||||
@@ -36,18 +37,18 @@ import org.springframework.batch.restart.GenericRestartData;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Simple Job Repository that stores Jobs, JobExecutions, Steps, and
|
||||
* StepExecutions using the provided JobDao and StepDao.
|
||||
* <p>
|
||||
*
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @see JobRepository
|
||||
* @see StepDao
|
||||
* @see JobDao
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class SimpleJobRepository implements JobRepository {
|
||||
|
||||
@@ -71,7 +72,7 @@ public class SimpleJobRepository implements JobRepository {
|
||||
* either creating a new job or finding an existing one, which will ensure
|
||||
* that the id field of the job is populated with the correct value.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* There are two ways in which the method determines if a job should be
|
||||
* created or an existing one should be returned. The first is
|
||||
@@ -82,20 +83,23 @@ public class SimpleJobRepository implements JobRepository {
|
||||
* (there must be at least 1) and it will be returned. If no job is found, a
|
||||
* new one will be created based on the configuration.
|
||||
* </p>
|
||||
*
|
||||
* @throws JobExecutionAlreadyRunningException
|
||||
*
|
||||
* @see JobRepository#findOrCreateJob(JobConfiguration, JobIdentifier)
|
||||
* @throws BatchRestartException if more than one JobInstance if found
|
||||
* or if JobInstance.getJobExecutionCount() is greater than JobConfiguration.getStartLimit()
|
||||
* @throws BatchRestartException
|
||||
* if more than one JobInstance if found or if
|
||||
* JobInstance.getJobExecutionCount() is greater than
|
||||
* JobConfiguration.getStartLimit()
|
||||
*/
|
||||
public JobInstance findOrCreateJob(JobConfiguration jobConfiguration, JobIdentifier runtimeInformation) {
|
||||
public JobExecution findOrCreateJob(JobConfiguration jobConfiguration,
|
||||
JobIdentifier runtimeInformation) throws JobExecutionAlreadyRunningException {
|
||||
|
||||
List jobs;
|
||||
|
||||
// Check if a job is restartable, if not, create and return a new job
|
||||
if (jobConfiguration.isRestartable() == false) {
|
||||
return createJob(jobConfiguration, runtimeInformation);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// find all jobs matching the runtime information.
|
||||
jobs = jobDao.findJobs(runtimeInformation);
|
||||
}
|
||||
@@ -103,24 +107,48 @@ public class SimpleJobRepository implements JobRepository {
|
||||
if (jobs.size() == 1) {
|
||||
// One job was found
|
||||
JobInstance job = (JobInstance) jobs.get(0);
|
||||
job.setSteps(findSteps(jobConfiguration.getStepConfigurations(), job));
|
||||
job.setSteps(findSteps(jobConfiguration.getStepConfigurations(),
|
||||
job));
|
||||
job.setJobExecutionCount(jobDao.getJobExecutionCount(job.getId()));
|
||||
if (job.getJobExecutionCount() > jobConfiguration.getStartLimit()) {
|
||||
throw new BatchRestartException("Restart Max exceeded for Job: " + job.toString());
|
||||
throw new BatchRestartException(
|
||||
"Restart Max exceeded for Job: " + job.toString());
|
||||
}
|
||||
return job;
|
||||
}
|
||||
else if (jobs.size() == 0) {
|
||||
List executions = jobDao.findJobExecutions(job);
|
||||
for (Iterator iterator = executions.iterator(); iterator.hasNext();) {
|
||||
JobExecution execution = (JobExecution) iterator.next();
|
||||
if (execution.isRunning()) {
|
||||
throw new JobExecutionAlreadyRunningException("A job execution for this job is already running: "+job);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Update the job, then if this method is transactional, and the
|
||||
* isolation level is SERIALIZABLE, another launcher trying to start
|
||||
* the same job in another thread or process will lose.
|
||||
*/
|
||||
jobDao.update(job);
|
||||
|
||||
return generateJobExecution(job);
|
||||
|
||||
} else if (jobs.size() == 0) {
|
||||
// no job found, create one
|
||||
return createJob(jobConfiguration, runtimeInformation);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// More than one job found, throw exception
|
||||
throw new BatchRestartException("Error restarting job, more than one JobInstance found for: "
|
||||
+ jobConfiguration.toString());
|
||||
throw new BatchRestartException(
|
||||
"Error restarting job, more than one JobInstance found for: "
|
||||
+ jobConfiguration.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private JobExecution generateJobExecution(JobInstance job) {
|
||||
JobExecution execution = job.createNewJobExecution();
|
||||
// Save the JobExecution so that it picks up an ID (useful for clients
|
||||
// monitoring asynchronous executions):
|
||||
saveOrUpdate(execution);
|
||||
return execution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save or Update a JobExecution. A JobExecution is considered one
|
||||
* 'execution' of a particular job. Therefore, it must have it's jobId field
|
||||
@@ -128,20 +156,22 @@ public class SimpleJobRepository implements JobRepository {
|
||||
* identifer, because it must be updatable separately. If an id isn't found,
|
||||
* a new JobExecution is created, if one is found, the current row is
|
||||
* updated.
|
||||
*
|
||||
* @param JobExecution to be stored.
|
||||
* @throws IllegalArgumentException if jobExecution is null.
|
||||
*
|
||||
* @param JobExecution
|
||||
* to be stored.
|
||||
* @throws IllegalArgumentException
|
||||
* if jobExecution is null.
|
||||
*/
|
||||
public void saveOrUpdate(JobExecution jobExecution) {
|
||||
|
||||
Assert.notNull(jobExecution, "JobExecution cannot be null.");
|
||||
Assert.notNull(jobExecution.getJobId(), "JobExecution must have a Job ID set.");
|
||||
Assert.notNull(jobExecution.getJobId(),
|
||||
"JobExecution must have a Job ID set.");
|
||||
|
||||
if (jobExecution.getId() == null) {
|
||||
// existing instance
|
||||
jobDao.save(jobExecution);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// new execution
|
||||
jobDao.update(jobExecution);
|
||||
}
|
||||
@@ -151,15 +181,20 @@ public class SimpleJobRepository implements JobRepository {
|
||||
* Update an existing job. A job must have been obtained from the
|
||||
* findOrCreateJob method, otherwise it is likely that the id is incorrect
|
||||
* or non-existant.
|
||||
*
|
||||
* @param job to be updated.
|
||||
* @throws IllegalArgumentException if Job or it's Id is null.
|
||||
*
|
||||
* @param job
|
||||
* to be updated.
|
||||
* @throws IllegalArgumentException
|
||||
* if Job or it's Id is null.
|
||||
*/
|
||||
public void update(JobInstance job) {
|
||||
|
||||
Assert.notNull(job, "Job cannot be null.");
|
||||
Assert.notNull(job.getId(), "Job cannot be updated if it's ID is null. It must be obtained"
|
||||
+ "from SimpleJobRepository.findOrCreateJob to be considered valid.");
|
||||
Assert
|
||||
.notNull(
|
||||
job.getId(),
|
||||
"Job cannot be updated if it's ID is null. It must be obtained"
|
||||
+ "from SimpleJobRepository.findOrCreateJob to be considered valid.");
|
||||
|
||||
jobDao.update(job);
|
||||
}
|
||||
@@ -169,20 +204,22 @@ public class SimpleJobRepository implements JobRepository {
|
||||
* saved and an id will be set, otherwise it will be updated. It should be
|
||||
* noted that assigning an ID randomly will likely cause an exception
|
||||
* depending on the StepDao implementation.
|
||||
*
|
||||
* @param StepExecution to be saved.
|
||||
* @throws IllegalArgumentException if stepExecution is null.
|
||||
*
|
||||
* @param StepExecution
|
||||
* to be saved.
|
||||
* @throws IllegalArgumentException
|
||||
* if stepExecution is null.
|
||||
*/
|
||||
public void saveOrUpdate(StepExecution stepExecution) {
|
||||
|
||||
Assert.notNull(stepExecution, "StepExecution cannot be null.");
|
||||
Assert.notNull(stepExecution.getStepId(), "StepExecution's Step Id cannot be null.");
|
||||
Assert.notNull(stepExecution.getStepId(),
|
||||
"StepExecution's Step Id cannot be null.");
|
||||
|
||||
if (stepExecution.getId() == null) {
|
||||
// new execution, obtain id and insert
|
||||
stepDao.save(stepExecution);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// existing execution, update
|
||||
stepDao.update(stepExecution);
|
||||
}
|
||||
@@ -190,15 +227,20 @@ public class SimpleJobRepository implements JobRepository {
|
||||
|
||||
/**
|
||||
* Update the given step.
|
||||
*
|
||||
* @param StepInstance to be updated.
|
||||
* @throws IllegalArgumentException if step or it's id is null.
|
||||
*
|
||||
* @param StepInstance
|
||||
* to be updated.
|
||||
* @throws IllegalArgumentException
|
||||
* if step or it's id is null.
|
||||
*/
|
||||
public void update(StepInstance step) {
|
||||
|
||||
Assert.notNull(step, "Step cannot be null.");
|
||||
Assert.notNull(step.getId(), "Step cannot be updated if it's ID is null. It must be obtained"
|
||||
+ "from SimpleJobRepository.findOrCreateJob to be considered valid.");
|
||||
Assert
|
||||
.notNull(
|
||||
step.getId(),
|
||||
"Step cannot be updated if it's ID is null. It must be obtained"
|
||||
+ "from SimpleJobRepository.findOrCreateJob to be considered valid.");
|
||||
|
||||
stepDao.update(step);
|
||||
|
||||
@@ -209,11 +251,15 @@ public class SimpleJobRepository implements JobRepository {
|
||||
* calling {@link JobDao#createJob(JobRuntimeInformation)} and then it's
|
||||
* list of StepConfigurations is passed to the createSteps method.
|
||||
*/
|
||||
private JobInstance createJob(JobConfiguration jobConfiguration, JobIdentifier runtimeInformation) {
|
||||
private JobExecution createJob(JobConfiguration jobConfiguration,
|
||||
JobIdentifier runtimeInformation) {
|
||||
|
||||
JobInstance job = jobDao.createJob(runtimeInformation);
|
||||
job.setSteps(createSteps(job, jobConfiguration.getStepConfigurations()));
|
||||
return job;
|
||||
job
|
||||
.setSteps(createSteps(job, jobConfiguration
|
||||
.getStepConfigurations()));
|
||||
JobExecution execution = generateJobExecution(job);
|
||||
return execution;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -225,9 +271,11 @@ public class SimpleJobRepository implements JobRepository {
|
||||
Iterator i = stepConfigurations.iterator();
|
||||
while (i.hasNext()) {
|
||||
StepConfiguration stepConfiguration = (StepConfiguration) i.next();
|
||||
StepInstance step = stepDao.createStep(job, stepConfiguration.getName());
|
||||
//Ensure valid restart data is being returned.
|
||||
if(step.getRestartData() == null || step.getRestartData().getProperties() == null){
|
||||
StepInstance step = stepDao.createStep(job, stepConfiguration
|
||||
.getName());
|
||||
// Ensure valid restart data is being returned.
|
||||
if (step.getRestartData() == null
|
||||
|| step.getRestartData().getProperties() == null) {
|
||||
step.setRestartData(new GenericRestartData(new Properties()));
|
||||
}
|
||||
steps.add(step);
|
||||
@@ -245,13 +293,18 @@ public class SimpleJobRepository implements JobRepository {
|
||||
while (i.hasNext()) {
|
||||
|
||||
StepConfiguration stepConfiguration = (StepConfiguration) i.next();
|
||||
StepInstance step = stepDao.findStep(job, stepConfiguration.getName());
|
||||
StepInstance step = stepDao.findStep(job, stepConfiguration
|
||||
.getName());
|
||||
if (step != null) {
|
||||
|
||||
step.setStepExecutionCount(stepDao.getStepExecutionCount(step.getId()));
|
||||
//Ensure valid restart data is being returned.
|
||||
if(step.getRestartData() == null || step.getRestartData().getProperties() == null){
|
||||
step.setRestartData(new GenericRestartData(new Properties()));
|
||||
step.setStepExecutionCount(stepDao.getStepExecutionCount(step
|
||||
.getId()));
|
||||
// Ensure valid restart data is being returned.
|
||||
if (step.getRestartData() == null
|
||||
|| step.getRestartData().getProperties() == null) {
|
||||
step
|
||||
.setRestartData(new GenericRestartData(
|
||||
new Properties()));
|
||||
}
|
||||
steps.add(step);
|
||||
}
|
||||
|
||||
@@ -26,14 +26,15 @@ import org.springframework.batch.core.domain.JobInstance;
|
||||
* Data Access Object for jobs.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface JobDao {
|
||||
|
||||
/**
|
||||
* Create a job using the provided JobIdentifier as the natural key.
|
||||
*
|
||||
* PostConditions: A valid job will be returned which contains an unique Id.
|
||||
* PostConditions: A valid job will be returned which has been persisted and
|
||||
* contains an unique Id.
|
||||
*
|
||||
* @param jobIdentifier
|
||||
* @return Job
|
||||
@@ -45,7 +46,8 @@ public interface JobDao {
|
||||
* Identifier are found, then a list of size 0 will be returned.
|
||||
*
|
||||
* @param jobIdentifier
|
||||
* @return List of {@link JobInstance} objects matching {@link JobIdentifier}
|
||||
* @return List of {@link JobInstance} objects matching
|
||||
* {@link JobIdentifier}
|
||||
*/
|
||||
public List findJobs(JobIdentifier jobIdentifier);
|
||||
|
||||
@@ -85,7 +87,7 @@ public interface JobDao {
|
||||
* @param job
|
||||
*/
|
||||
public int getJobExecutionCount(Long jobId);
|
||||
|
||||
|
||||
/**
|
||||
* Return list of JobExecutions for given job.
|
||||
*
|
||||
|
||||
@@ -128,9 +128,8 @@ public class DefaultJobExecutorTests extends TestCase {
|
||||
|
||||
jobIdentifer = new SimpleJobIdentifier("TestJob");
|
||||
|
||||
job = jobRepository.findOrCreateJob(jobConfiguration, jobIdentifer);
|
||||
|
||||
jobExecution = new JobExecution(job);
|
||||
jobExecution = jobRepository.findOrCreateJob(jobConfiguration, jobIdentifer);
|
||||
job = jobExecution.getJob();
|
||||
|
||||
List steps = job.getSteps();
|
||||
step1 = (StepInstance) steps.get(0);
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.batch.execution.launch;
|
||||
|
||||
import org.springframework.batch.execution.AbstractExceptionTests;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JobExecutionAlreadyRunningExceptionTests extends AbstractExceptionTests {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String)
|
||||
*/
|
||||
public Exception getException(String msg) throws Exception {
|
||||
return new JobExecutionAlreadyRunningException(msg);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable)
|
||||
*/
|
||||
public Exception getException(String msg, Throwable t) throws Exception {
|
||||
return new JobExecutionAlreadyRunningException(msg, t);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import java.util.Properties;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.AbstractMatcher;
|
||||
import org.easymock.MockControl;
|
||||
import org.springframework.batch.core.configuration.JobConfiguration;
|
||||
import org.springframework.batch.core.configuration.JobConfigurationLocator;
|
||||
@@ -32,6 +31,7 @@ import org.springframework.batch.core.configuration.NoSuchJobConfigurationExcept
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.executor.JobExecutor;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
|
||||
import org.springframework.batch.io.exception.BatchCriticalException;
|
||||
@@ -97,7 +97,7 @@ public class SimpleJobExecutorFacadeTests extends TestCase {
|
||||
}
|
||||
|
||||
private JobInstance setUpFacadeForNormalStart()
|
||||
throws NoSuchJobConfigurationException {
|
||||
throws Exception {
|
||||
jobIdentifier = new SimpleJobIdentifier("bar");
|
||||
jobExecutor = new JobExecutor() {
|
||||
public ExitStatus run(JobConfiguration configuration,
|
||||
@@ -110,18 +110,7 @@ public class SimpleJobExecutorFacadeTests extends TestCase {
|
||||
JobInstance job = new JobInstance(jobIdentifier);
|
||||
jobExecution = new JobExecution(job);
|
||||
jobRepository.findOrCreateJob(jobConfiguration, jobIdentifier);
|
||||
jobRepositoryControl.setReturnValue(job);
|
||||
jobRepository.saveOrUpdate(jobExecution);
|
||||
jobRepositoryControl.setMatcher(new AbstractMatcher() {
|
||||
protected boolean argumentMatches(Object expected, Object actual) {
|
||||
if (actual instanceof JobExecution) {
|
||||
jobExecution = (JobExecution) actual;
|
||||
return true;
|
||||
} else {
|
||||
return super.argumentMatches(expected, actual);
|
||||
}
|
||||
}
|
||||
});
|
||||
jobRepositoryControl.setReturnValue(jobExecution);
|
||||
jobRepositoryControl.replay();
|
||||
jobExecutorFacade
|
||||
.setJobConfigurationLocator(new JobConfigurationLocator() {
|
||||
|
||||
@@ -118,7 +118,7 @@ public class SimpleJobTests extends TestCase {
|
||||
jobConfiguration.addStep(new SimpleStepConfiguration(getTasklet("foo", "bar")));
|
||||
jobConfiguration.addStep(new SimpleStepConfiguration(getTasklet("spam")));
|
||||
|
||||
JobInstance job = repository.findOrCreateJob(jobConfiguration, runtimeInformation);
|
||||
JobInstance job = repository.findOrCreateJob(jobConfiguration, runtimeInformation).getJob();
|
||||
|
||||
assertEquals(job.getName(), "real.job");
|
||||
|
||||
@@ -169,8 +169,8 @@ public class SimpleJobTests extends TestCase {
|
||||
});
|
||||
jobConfiguration.addStep(step);
|
||||
|
||||
JobInstance job = repository.findOrCreateJob(jobConfiguration, runtimeInformation);
|
||||
JobExecution jobExecution = new JobExecution(job);
|
||||
JobExecution jobExecution = repository.findOrCreateJob(jobConfiguration, runtimeInformation);
|
||||
JobInstance job = jobExecution.getJob();
|
||||
jobExecutor.run(jobConfiguration, jobExecution);
|
||||
|
||||
assertEquals(BatchStatus.COMPLETED, job.getStatus());
|
||||
@@ -193,10 +193,10 @@ public class SimpleJobTests extends TestCase {
|
||||
});
|
||||
jobConfiguration.addStep(step);
|
||||
|
||||
JobInstance job = repository.findOrCreateJob(jobConfiguration, runtimeInformation);
|
||||
JobExecution jobExecutionContext = new JobExecution(job);
|
||||
JobExecution jobExecution = repository.findOrCreateJob(jobConfiguration, runtimeInformation);
|
||||
JobInstance job = jobExecution.getJob();
|
||||
try {
|
||||
jobExecutor.run(jobConfiguration, jobExecutionContext);
|
||||
jobExecutor.run(jobConfiguration, jobExecution);
|
||||
fail("Expected RuntimeException");
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.batch.core.configuration.NoSuchJobConfigurationExcept
|
||||
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.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.runtime.SimpleJobIdentifier;
|
||||
import org.springframework.batch.core.runtime.SimpleJobIdentifierFactory;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
package org.springframework.batch.execution.repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.ArgumentsMatcher;
|
||||
import org.easymock.MockControl;
|
||||
import org.springframework.batch.core.configuration.JobConfiguration;
|
||||
import org.springframework.batch.core.configuration.StepConfiguration;
|
||||
@@ -74,6 +76,8 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
|
||||
List steps;
|
||||
|
||||
private JobExecution jobExecution;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
|
||||
jobDao = (JobDao) jobDaoControl.getMock();
|
||||
@@ -96,8 +100,13 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
stepConfigurations.add(stepConfiguration2);
|
||||
|
||||
jobConfiguration.setSteps(stepConfigurations);
|
||||
|
||||
databaseJob = new JobInstance(jobRuntimeInformation, new Long(1));
|
||||
|
||||
databaseJob = new JobInstance(jobRuntimeInformation, new Long(1)) {
|
||||
public JobExecution createNewJobExecution() {
|
||||
jobExecution = super.createNewJobExecution();
|
||||
return jobExecution;
|
||||
}
|
||||
};
|
||||
|
||||
databaseStep1 = new StepInstance(new Long(1));
|
||||
databaseStep2 = new StepInstance(new Long(2));
|
||||
@@ -110,7 +119,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
/*
|
||||
* Test a restartable job, that has not been run before.
|
||||
*/
|
||||
public void testCreateRestartableJob(){
|
||||
public void testCreateRestartableJob() throws Exception {
|
||||
|
||||
List jobs = new ArrayList();
|
||||
|
||||
@@ -122,9 +131,18 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
stepDaoControl.setReturnValue(databaseStep1);
|
||||
stepDao.createStep(databaseJob, "TestStep2");
|
||||
stepDaoControl.setReturnValue(databaseStep2);
|
||||
jobDao.save(new JobExecution(databaseJob));
|
||||
jobDaoControl.setMatcher(new ArgumentsMatcher(){
|
||||
public boolean matches(Object[] expected, Object[] actual) {
|
||||
return ((JobExecution) actual[0]).getJob().equals(databaseJob);
|
||||
}
|
||||
public String toString(Object[] arguments) {
|
||||
return ""+arguments[0];
|
||||
}
|
||||
});
|
||||
stepDaoControl.replay();
|
||||
jobDaoControl.replay();
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation).getJob();
|
||||
assertTrue(job.equals(databaseJob));
|
||||
List jobSteps = job.getSteps();
|
||||
Iterator it = jobSteps.iterator();
|
||||
@@ -134,7 +152,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
assertTrue(step.equals(databaseStep2));
|
||||
}
|
||||
|
||||
public void testRestartedJob(){
|
||||
public void testRestartedJob() throws Exception{
|
||||
List jobs = new ArrayList();
|
||||
jobDao.findJobs(jobRuntimeInformation);
|
||||
jobs.add(databaseJob);
|
||||
@@ -150,8 +168,24 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
stepDaoControl.replay();
|
||||
jobDao.getJobExecutionCount(databaseJob.getId());
|
||||
jobDaoControl.setReturnValue(1);
|
||||
jobDao.findJobExecutions(databaseJob);
|
||||
final List executions = new ArrayList();
|
||||
jobDaoControl.setReturnValue(executions);
|
||||
jobDao.update(databaseJob);
|
||||
jobDao.save(new JobExecution(databaseJob));
|
||||
jobDaoControl.setMatcher(new ArgumentsMatcher(){
|
||||
public boolean matches(Object[] expected, Object[] actual) {
|
||||
JobExecution execution = (JobExecution) actual[0];
|
||||
executions.add(execution);
|
||||
return execution.getJob().equals(databaseJob);
|
||||
}
|
||||
public String toString(Object[] arguments) {
|
||||
return ""+arguments[0];
|
||||
}
|
||||
});
|
||||
jobDaoControl.setVoidCallable();
|
||||
jobDaoControl.replay();
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation).getJob();
|
||||
assertTrue(job.equals(databaseJob));
|
||||
List jobSteps = job.getSteps();
|
||||
Iterator it = jobSteps.iterator();
|
||||
@@ -164,7 +198,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
}
|
||||
|
||||
//Test that a restartable job that has multiple instances throws an exception.
|
||||
public void testFindRestartableJobWithMultipleInstances(){
|
||||
public void testFindRestartableJobWithMultipleInstances() throws Exception{
|
||||
|
||||
List jobs = new ArrayList();
|
||||
jobs.add(databaseJob);
|
||||
@@ -183,7 +217,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
jobDaoControl.verify();
|
||||
}
|
||||
|
||||
public void testRestartJobStartLimitExceeded(){
|
||||
public void testRestartJobStartLimitExceeded() throws Exception{
|
||||
|
||||
jobConfiguration.setStartLimit(1);
|
||||
|
||||
@@ -216,7 +250,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
stepDaoControl.verify();
|
||||
}
|
||||
|
||||
public void testCreateNonRestartableJob(){
|
||||
public void testCreateNonRestartableJob() throws Exception{
|
||||
|
||||
List jobs = new ArrayList();
|
||||
jobConfiguration.setRestartable(false);
|
||||
@@ -229,9 +263,18 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
stepDaoControl.setReturnValue(databaseStep1);
|
||||
stepDao.createStep(databaseJob, "TestStep2");
|
||||
stepDaoControl.setReturnValue(databaseStep2);
|
||||
jobDao.save(new JobExecution(databaseJob));
|
||||
jobDaoControl.setMatcher(new ArgumentsMatcher(){
|
||||
public boolean matches(Object[] expected, Object[] actual) {
|
||||
return ((JobExecution) actual[0]).getJob().equals(databaseJob);
|
||||
}
|
||||
public String toString(Object[] arguments) {
|
||||
return ""+arguments[0];
|
||||
}
|
||||
});
|
||||
stepDaoControl.replay();
|
||||
jobDaoControl.replay();
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation).getJob();
|
||||
assertTrue(job.equals(databaseJob));
|
||||
List jobSteps = job.getSteps();
|
||||
Iterator it = jobSteps.iterator();
|
||||
@@ -347,7 +390,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
* Test to ensure that if a StepDao returns invalid
|
||||
* restart data, it is corrected.
|
||||
*/
|
||||
public void testCreateStepsFixesInvalidRestartData(){
|
||||
public void testCreateStepsFixesInvalidRestartData() throws Exception{
|
||||
|
||||
List jobs = new ArrayList();
|
||||
|
||||
@@ -361,9 +404,18 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
stepDao.createStep(databaseJob, "TestStep2");
|
||||
databaseStep2.setRestartData(new GenericRestartData(null));
|
||||
stepDaoControl.setReturnValue(databaseStep2);
|
||||
jobDao.save(new JobExecution(databaseJob));
|
||||
jobDaoControl.setMatcher(new ArgumentsMatcher(){
|
||||
public boolean matches(Object[] expected, Object[] actual) {
|
||||
return ((JobExecution) actual[0]).getJob().equals(databaseJob);
|
||||
}
|
||||
public String toString(Object[] arguments) {
|
||||
return ""+arguments[0];
|
||||
}
|
||||
});
|
||||
stepDaoControl.replay();
|
||||
jobDaoControl.replay();
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation).getJob();
|
||||
List jobSteps = job.getSteps();
|
||||
Iterator it = jobSteps.iterator();
|
||||
StepInstance step = (StepInstance) it.next();
|
||||
@@ -374,7 +426,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
assertTrue(step.getRestartData().getProperties().isEmpty());
|
||||
}
|
||||
|
||||
public void testFindStepsFixesInvalidRestartData(){
|
||||
public void testFindStepsFixesInvalidRestartData() throws Exception{
|
||||
List jobs = new ArrayList();
|
||||
jobDao.findJobs(jobRuntimeInformation);
|
||||
jobs.add(databaseJob);
|
||||
@@ -392,8 +444,21 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
stepDaoControl.replay();
|
||||
jobDao.getJobExecutionCount(databaseJob.getId());
|
||||
jobDaoControl.setReturnValue(1);
|
||||
jobDao.findJobExecutions(databaseJob);
|
||||
jobDaoControl.setReturnValue(new ArrayList());
|
||||
jobDao.update(databaseJob);
|
||||
jobDaoControl.setVoidCallable();
|
||||
jobDao.save(new JobExecution(databaseJob));
|
||||
jobDaoControl.setMatcher(new ArgumentsMatcher(){
|
||||
public boolean matches(Object[] expected, Object[] actual) {
|
||||
return ((JobExecution) actual[0]).getJob().equals(databaseJob);
|
||||
}
|
||||
public String toString(Object[] arguments) {
|
||||
return ""+arguments[0];
|
||||
}
|
||||
});
|
||||
jobDaoControl.replay();
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation);
|
||||
JobInstance job = jobRepository.findOrCreateJob(jobConfiguration, jobRuntimeInformation).getJob();
|
||||
assertTrue(job.equals(databaseJob));
|
||||
List jobSteps = job.getSteps();
|
||||
Iterator it = jobSteps.iterator();
|
||||
|
||||
@@ -32,7 +32,7 @@ public class JobRepositorySupport implements JobRepository {
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.container.common.repository.JobRepository#findOrCreateJob(org.springframework.batch.container.common.domain.JobConfiguration)
|
||||
*/
|
||||
public JobInstance findOrCreateJob(JobConfiguration jobConfiguration, JobIdentifier runtimeInformation) {
|
||||
public JobExecution findOrCreateJob(JobConfiguration jobConfiguration, JobIdentifier runtimeInformation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public class StepExecutorInterruptionTests extends TestCase {
|
||||
|
||||
private SimpleStepExecutor executor;
|
||||
|
||||
public void setUp() {
|
||||
public void setUp() throws Exception {
|
||||
|
||||
jobRepository = new SimpleJobRepository(jobDao, stepDao);
|
||||
|
||||
@@ -65,7 +65,7 @@ public class StepExecutorInterruptionTests extends TestCase {
|
||||
jobConfiguration.addStep(stepConfiguration);
|
||||
JobIdentifier runtimeInformation = new SimpleJobIdentifier("TestJob");
|
||||
jobConfiguration.setBeanName("testJob");
|
||||
job = jobRepository.findOrCreateJob(jobConfiguration, runtimeInformation);
|
||||
job = jobRepository.findOrCreateJob(jobConfiguration, runtimeInformation).getJob();
|
||||
executor = new SimpleStepExecutor();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user