OPEN - issue BATCH-814: JobRepository should not require Step or Job (only their names)

Fixed the step execution methods (not job execution yet)
This commit is contained in:
dsyer
2008-09-04 15:01:28 +00:00
parent 783dcef9ce
commit 4726eeaa77
13 changed files with 63 additions and 59 deletions

View File

@@ -12,16 +12,16 @@ public class ClassPathXmlApplicationContextFactory implements ApplicationContext
private ConfigurableApplicationContext parent;
private Resource[] path;
private Resource path;
/**
* Setter for the path to the xml to load to create an
* {@link ApplicationContext}. Can include wild cards as per the usual
* Spring resource resolution.
* {@link ApplicationContext}. Use imports to centralise the configuration in
* one file.
*
* @param path the resource path to the xml to load for the child context.
*/
public void setPath(Resource[] path) {
public void setPath(Resource path) {
this.path = path;
}
@@ -41,7 +41,7 @@ public class ClassPathXmlApplicationContextFactory implements ApplicationContext
* @see ApplicationContextFactory#createApplicationContext()
*/
public ConfigurableApplicationContext createApplicationContext() {
if (path==null) {
if (path == null) {
return parent;
}
return new ResourceXmlApplicationContext(parent);
@@ -49,7 +49,7 @@ public class ClassPathXmlApplicationContextFactory implements ApplicationContext
/**
* @author Dave Syer
*
*
*/
private final class ResourceXmlApplicationContext extends AbstractXmlApplicationContext {
/**
@@ -61,9 +61,8 @@ public class ClassPathXmlApplicationContextFactory implements ApplicationContext
}
protected Resource[] getConfigResources() {
return path;
return new Resource[] {path};
}
}
}

View File

@@ -48,7 +48,7 @@ public class ClassPathXmlJobRegistry implements ListableJobRegistry, Application
jobRegistry = new MapJobRegistry();
for(Resource resource:jobPaths){
ClassPathXmlApplicationContextFactory applicationContextFactory = new ClassPathXmlApplicationContextFactory();
applicationContextFactory.setPath(new Resource[]{resource});
applicationContextFactory.setPath(resource);
applicationContextFactory.setApplicationContext(parent);
ApplicationContext context = applicationContextFactory.createApplicationContext();
String[] names = context.getBeanNamesForType(Job.class);

View File

@@ -83,7 +83,7 @@ public class SimpleJob extends AbstractJob {
updateStatus(execution, BatchStatus.STARTED);
currentStepExecution = execution.createStepExecution(step.getName());
StepExecution lastStepExecution = getJobRepository().getLastStepExecution(jobInstance, step);
StepExecution lastStepExecution = getJobRepository().getLastStepExecution(jobInstance, step.getName());
boolean isRestart = (lastStepExecution != null && !lastStepExecution.getStatus().equals(
BatchStatus.COMPLETED)) ? true : false;
@@ -155,7 +155,7 @@ public class SimpleJob extends AbstractJob {
BatchStatus stepStatus;
// if the last execution is null, the step has never been executed.
StepExecution lastStepExecution = getJobRepository().getLastStepExecution(jobInstance, step);
StepExecution lastStepExecution = getJobRepository().getLastStepExecution(jobInstance, step.getName());
if (lastStepExecution == null) {
stepStatus = BatchStatus.STARTING;
}
@@ -175,7 +175,7 @@ public class SimpleJob extends AbstractJob {
return false;
}
if (getJobRepository().getStepExecutionCount(jobInstance, step) < step.getStartLimit()) {
if (getJobRepository().getStepExecutionCount(jobInstance, step.getName()) < step.getStartLimit()) {
// step start count is less than start max, return true
return true;
}

View File

@@ -122,7 +122,7 @@ public class JobRegistryBackgroundJobRunner {
for (int k = 0; k < names.length; k++) {
ClassPathXmlApplicationContextFactory factory = new ClassPathXmlApplicationContextFactory();
factory.setApplicationContext(parentContext);
factory.setPath(new Resource[] { path });
factory.setPath(path);
logger.info("Registering Job definition: " + names[k]);
registry.register(new ApplicationContextJobFactory(factory, names[k]));
}

View File

@@ -32,16 +32,19 @@ import org.springframework.core.task.TaskExecutor;
import org.springframework.util.Assert;
/**
* Simple implementation of the {@link JobLauncher} interface. The Spring Core {@link TaskExecutor}
* interface is used to launch a {@link Job}. This means that the type of executor set is very
* important. If a {@link SyncTaskExecutor} is used, then the job will be processed <strong>within
* the same thread that called the launcher.</strong> Care should be taken to ensure any users of
* this class understand fully whether or not the implementation of TaskExecutor used will start
* tasks synchronously or asynchronously. The default setting uses a synchronous task executor.
* Simple implementation of the {@link JobLauncher} interface. The Spring Core
* {@link TaskExecutor} interface is used to launch a {@link Job}. This means
* that the type of executor set is very important. If a
* {@link SyncTaskExecutor} is used, then the job will be processed
* <strong>within the same thread that called the launcher.</strong> Care should
* be taken to ensure any users of this class understand fully whether or not
* the implementation of TaskExecutor used will start tasks synchronously or
* asynchronously. The default setting uses a synchronous task executor.
*
* There is only one required dependency of this Launcher, a {@link JobRepository}. The
* JobRepository is used to obtain a valid JobExecution. The Repository must be used because the
* provided {@link Job} could be a restart of an existing {@link JobInstance}, and only the
* There is only one required dependency of this Launcher, a
* {@link JobRepository}. The JobRepository is used to obtain a valid
* JobExecution. The Repository must be used because the provided {@link Job}
* could be a restart of an existing {@link JobInstance}, and only the
* Repository can reliably recreate it.
*
* @author Lucas Ward
@@ -58,20 +61,22 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean {
private TaskExecutor taskExecutor;
/**
* Run the provided job with the given {@link JobParameters}. The {@link JobParameters} will be
* used to determine if this is an execution of an existing job instance, or if a new one should
* be created.
* Run the provided job with the given {@link JobParameters}. The
* {@link JobParameters} will be used to determine if this is an execution
* of an existing job instance, or if a new one should be created.
*
* @param job the job to be run.
* @param jobParameters the {@link JobParameters} for this particular execution.
* @return JobExecutionAlreadyRunningException if the JobInstance already exists and has an
* execution already running.
* @throws JobRestartException if the execution would be a re-start, but a re-start is either
* not allowed or not needed.
* @throws JobInstanceAlreadyCompleteException
* @param jobParameters the {@link JobParameters} for this particular
* execution.
* @return JobExecutionAlreadyRunningException if the JobInstance already
* exists and has an execution already running.
* @throws JobRestartException if the execution would be a re-start, but a
* re-start is either not allowed or not needed.
* @throws JobInstanceAlreadyCompleteException if this instance has already
* completed successfully
*/
public JobExecution run(final Job job, final JobParameters jobParameters)
throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
Assert.notNull(job, "The Job must not be null.");
Assert.notNull(jobParameters, "The JobParameters must not be null.");
@@ -85,8 +90,9 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean {
logger.info("Job: [" + job + "] launched with the following parameters: [" + jobParameters + "]");
job.execute(jobExecution);
logger.info("Job: [" + job + "] completed successfully with the following parameters: ["
+ jobParameters + "]");
} catch (Throwable t) {
+ jobParameters + "]");
}
catch (Throwable t) {
logger.info("Job: [" + job + "] failed with the following parameters: [" + jobParameters + "]", t);
rethrow(t);
}
@@ -122,7 +128,8 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean {
}
/**
* Ensure the required dependencies of a {@link JobRepository} have been set.
* Ensure the required dependencies of a {@link JobRepository} have been
* set.
*/
public void afterPropertiesSet() throws Exception {
Assert.state(jobRepository != null, "A JobRepository has not been set.");

View File

@@ -104,13 +104,15 @@ public interface JobRepository {
void updateExecutionContext(StepExecution stepExecution);
/**
* @param stepName the name of the step execution that might have run.
* @return the last execution of step for the given job instance.
*/
StepExecution getLastStepExecution(JobInstance jobInstance, Step step);
StepExecution getLastStepExecution(JobInstance jobInstance, String stepName);
/**
* @param stepName the name of the step execution that might have run.
* @return the execution count of the step within the given job instance.
*/
int getStepExecutionCount(JobInstance jobInstance, Step step);
int getStepExecutionCount(JobInstance jobInstance, String stepName);
}

View File

@@ -25,7 +25,6 @@ import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
@@ -270,11 +269,11 @@ public class SimpleJobRepository implements JobRepository {
/**
* @return the last execution of the step within given job instance
*/
public StepExecution getLastStepExecution(JobInstance jobInstance, Step step) {
public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) {
List<JobExecution> jobExecutions = jobExecutionDao.findJobExecutions(jobInstance);
List<StepExecution> stepExecutions = new ArrayList<StepExecution>(jobExecutions.size());
for (JobExecution jobExecution : jobExecutions) {
StepExecution stepExecution = stepExecutionDao.getStepExecution(jobExecution, step.getName());
StepExecution stepExecution = stepExecutionDao.getStepExecution(jobExecution, stepName);
if (stepExecution != null) {
stepExecutions.add(stepExecution);
}
@@ -298,11 +297,11 @@ public class SimpleJobRepository implements JobRepository {
/**
* @return number of executions of the step within given job instance
*/
public int getStepExecutionCount(JobInstance jobInstance, Step step) {
public int getStepExecutionCount(JobInstance jobInstance, String stepName) {
int count = 0;
List<JobExecution> jobExecutions = jobExecutionDao.findJobExecutions(jobInstance);
for (JobExecution jobExecution : jobExecutions) {
if (stepExecutionDao.getStepExecution(jobExecution, step.getName()) != null) {
if (stepExecutionDao.getStepExecution(jobExecution, stepName) != null) {
count++;
}
}

View File

@@ -19,7 +19,6 @@ import junit.framework.TestCase;
import org.springframework.batch.core.Job;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;
/**
@@ -31,12 +30,12 @@ public class ClassPathXmlApplicationContextFactoryTests extends TestCase {
private ClassPathXmlApplicationContextFactory factory = new ClassPathXmlApplicationContextFactory();
public void testCreateJob() {
factory.setPath(new Resource[] {new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "trivial-context.xml"))});
factory.setPath(new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "trivial-context.xml")));
assertNotNull(factory.createApplicationContext());
}
public void testGetJobName() {
factory.setPath(new Resource[] {new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "trivial-context.xml"))});
factory.setPath(new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "trivial-context.xml")));
assertEquals("test-job", factory.createApplicationContext().getBeanNamesForType(Job.class)[0]);
}

View File

@@ -123,8 +123,8 @@ public class SimpleJobRepositoryIntegrationTests {
jobRepository.update(firstJobExec);
jobRepository.add(firstStepExec);
assertEquals(1, jobRepository.getStepExecutionCount(firstJobExec.getJobInstance(), step));
assertEquals(firstStepExec, jobRepository.getLastStepExecution(firstJobExec.getJobInstance(), step));
assertEquals(1, jobRepository.getStepExecutionCount(firstJobExec.getJobInstance(), step.getName()));
assertEquals(firstStepExec, jobRepository.getLastStepExecution(firstJobExec.getJobInstance(), step.getName()));
// first execution failed
firstJobExec.setStartTime(new Date(4));
@@ -142,8 +142,8 @@ public class SimpleJobRepositoryIntegrationTests {
jobRepository.update(secondJobExec);
jobRepository.add(secondStepExec);
assertEquals(2, jobRepository.getStepExecutionCount(secondJobExec.getJobInstance(), step));
assertEquals(secondStepExec, jobRepository.getLastStepExecution(secondJobExec.getJobInstance(), step));
assertEquals(2, jobRepository.getStepExecutionCount(secondJobExec.getJobInstance(), step.getName()));
assertEquals(secondStepExec, jobRepository.getLastStepExecution(secondJobExec.getJobInstance(), step.getName()));
}
/*
@@ -166,7 +166,7 @@ public class SimpleJobRepositoryIntegrationTests {
jobRepository.add(stepExec);
jobRepository.updateExecutionContext(stepExec);
StepExecution retrievedStepExec = jobRepository.getLastStepExecution(jobExec.getJobInstance(), step);
StepExecution retrievedStepExec = jobRepository.getLastStepExecution(jobExec.getJobInstance(), step.getName());
assertEquals(stepExec, retrievedStepExec);
assertEquals(ctx, retrievedStepExec.getExecutionContext());

View File

@@ -19,7 +19,6 @@ import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.repository.JobRepository;
@@ -48,11 +47,11 @@ public class JobRepositorySupport implements JobRepository {
public void update(JobInstance job) {
}
public StepExecution getLastStepExecution(JobInstance jobInstance, Step step) {
public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) {
return null;
}
public int getStepExecutionCount(JobInstance jobInstance, Step step) {
public int getStepExecutionCount(JobInstance jobInstance, String stepName) {
return 0;
}

View File

@@ -141,7 +141,7 @@ public class ChunkOrientedStepIntegrationTests {
catch (RuntimeException e) {
assertEquals(BatchStatus.UNKNOWN, stepExecution.getStatus());
StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobExecution.getJobInstance(), step);
StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobExecution.getJobInstance(), step.getName());
assertEquals(lastStepExecution, stepExecution);
assertFalse(lastStepExecution == stepExecution);

View File

@@ -72,7 +72,7 @@ public class StepExecutionMessageHandler {
StepExecution stepExecution = jobExecution.createStepExecution(step.getName());
try {
StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step);
StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step.getName());
// Even if it completed successfully we want to pass on the output
// attributes, so set up the execution context here if it is
@@ -176,7 +176,7 @@ public class StepExecutionMessageHandler {
return false;
}
if (jobRepository.getStepExecutionCount(lastStepExecution.getJobExecution().getJobInstance(), step) < step
if (jobRepository.getStepExecutionCount(lastStepExecution.getJobExecution().getJobInstance(), step.getName()) < step
.getStartLimit()) {
// step start count is less than start max, return true
return true;

View File

@@ -19,7 +19,6 @@ import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
@@ -43,14 +42,14 @@ public class JobRepositorySupport implements JobRepository {
/* (non-Javadoc)
* @see org.springframework.batch.core.repository.JobRepository#getLastStepExecution(org.springframework.batch.core.JobInstance, org.springframework.batch.core.Step)
*/
public StepExecution getLastStepExecution(JobInstance jobInstance, Step step) {
public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) {
return null;
}
/* (non-Javadoc)
* @see org.springframework.batch.core.repository.JobRepository#getStepExecutionCount(org.springframework.batch.core.JobInstance, org.springframework.batch.core.Step)
*/
public int getStepExecutionCount(JobInstance jobInstance, Step step) {
public int getStepExecutionCount(JobInstance jobInstance, String stepName) {
return 0;
}