diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java b/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java index 515dbd501..fdd0b7b70 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java @@ -15,7 +15,6 @@ */ package org.springframework.batch.core; - /** * Batch domain object representing a job. Job is an explicit abstraction * representing the configuration of a job specified by a developer. It should @@ -40,4 +39,9 @@ public interface Job { */ void execute(JobExecution execution) throws JobExecutionException; + /** + * @return in incrementer to be used for creating new parameters + */ + JobParametersIncrementer getJobParametersIncrementer(); + } \ No newline at end of file diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersIncrementer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersIncrementer.java index 113697a84..96b48897b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersIncrementer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersIncrementer.java @@ -15,7 +15,6 @@ */ package org.springframework.batch.core; - /** * Interface for obtaining the next {@link JobParameters} in a sequence. * @@ -23,7 +22,15 @@ package org.springframework.batch.core; * */ public interface JobParametersIncrementer { - + + /** + * Increment the provided parameters. If the input is empty, then this + * should return a bootstrap or initial value to be used on the first + * instance of a job. + * + * @param parameters the last value used + * @return the next value to use + */ JobParameters getNext(JobParameters parameters); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java index 71ae91804..93afed1bd 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java @@ -18,6 +18,7 @@ package org.springframework.batch.core.configuration.support; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobExecutionException; +import org.springframework.batch.core.JobParametersIncrementer; import org.springframework.batch.core.configuration.JobFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; @@ -116,6 +117,13 @@ public class ApplicationContextJobFactory implements JobFactory { return delegate.isRestartable(); } + /** + * @see org.springframework.batch.core.Job#getJobParametersIncrementer() + */ + public JobParametersIncrementer getJobParametersIncrementer() { + return delegate.getJobParametersIncrementer(); + } + } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/BatchMetaDataExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/BatchMetaDataExplorer.java index 06aa8bb1e..c4beaaa6e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/BatchMetaDataExplorer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/BatchMetaDataExplorer.java @@ -15,13 +15,11 @@ */ package org.springframework.batch.core.explore; -import java.util.Collection; -import java.util.Date; -import java.util.EnumSet; +import java.util.List; -import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; /** * @author Dave Syer @@ -29,23 +27,24 @@ import org.springframework.batch.core.JobInstance; */ public interface BatchMetaDataExplorer { - int countJobExecutionsByStatus(EnumSet statuses); + /** + * @param jobName the name of the job to query + * @param count the maximum number of instances to return + * @return the latest {@link JobInstance} values up to a maximum of count values + */ + List getLastJobInstances(String jobName, int count); /** - * @param statuses the status values to search - * @param start the start record (defaults to 0) - * @param count the maximum number of objects to return - * @return the {@link JobExecution} objects that have the provided status, - * sorted in reverse order by start time. + * @param jobName the name of the job + * @param jobParameters the parameters to match + * @return true if a {@link JobInstance} already exists for this job name and job parameters */ - Collection findJobExecutionsByStatus(EnumSet statuses, int start, int count); - - int countJobExecutionsByDate(Date from, Date to); + boolean isJobInstanceExists(String jobName, JobParameters jobParameters); - Collection findJobExecutionsByDate(Date from, Date to, int start, int count); - - Collection findJobInstancesByJobName(String jobName); - - Collection getJobExecutionsForJobInstance(JobInstance jobInstance); + /** + * @param executionId + * @return the {@link JobExecution} with this id, or null + */ + JobExecution getJobExecution(Long executionId); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java index f6a4a01f0..1630dc536 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java @@ -21,6 +21,7 @@ import java.util.List; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecutionListener; +import org.springframework.batch.core.JobParametersIncrementer; import org.springframework.batch.core.Step; import org.springframework.batch.core.listener.CompositeExecutionJobListener; import org.springframework.batch.core.repository.JobRepository; @@ -50,6 +51,8 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea private CompositeExecutionJobListener listener = new CompositeExecutionJobListener(); + private JobParametersIncrementer jobParametersIncrementer; + /** * Default constructor. */ @@ -126,6 +129,21 @@ public abstract class AbstractJob implements Job, BeanNameAware, InitializingBea public boolean isRestartable() { return restartable; } + + /** + * Public setter for the {@link JobParametersIncrementer}. + * @param jobParametersIncrementer the {@link JobParametersIncrementer} to set + */ + public void setJobParametersIncrementer(JobParametersIncrementer jobParametersIncrementer) { + this.jobParametersIncrementer = jobParametersIncrementer; + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.Job#getJobParametersIncrementer() + */ + public JobParametersIncrementer getJobParametersIncrementer() { + return this.jobParametersIncrementer; + } public String toString() { return ClassUtils.getShortName(getClass()) + ": [name=" + name + "]"; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobOperator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobOperator.java index 153e7c04e..f9a558ca0 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobOperator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobOperator.java @@ -19,6 +19,11 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParametersIncrementer; +import org.springframework.batch.core.UnexpectedJobExecutionException; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; import org.springframework.batch.core.repository.JobRestartException; @@ -45,9 +50,28 @@ public interface JobOperator { JobRestartException; Long resume(Long executionId) throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException, - NoSuchJobException; + NoSuchJobException, JobRestartException; - Long startNextInstance(String jobName) throws NoSuchJobException, JobParametersIncrementerNotFoundException; + /** + * Launch the next in a sequence of {@link JobInstance} determined by the + * {@link JobParametersIncrementer} attached to the specified job. If the + * previous instance is still in a failed state, this method should still + * create a new instance and run it with different parameters (as long as + * the {@link JobParametersIncrementer} is working).

+ * + * The last three exception described below should be extremely unlikely, + * but cannot be ruled out entirely. It points to some other thread or + * process trying to use this method (or a similar one) at the same time. + * + * @param jobName the name of the job to launch + * @return the {@link JobExecution} id of the execution created when the job + * is launched + * @throws NoSuchJobException if there is no such job definition available + * @throws JobParametersNotFoundException if the parameters cannot be found + * @throws UnexpectedJobExecutionException if an unexpected condition arises + */ + Long startNextInstance(String jobName) throws NoSuchJobException, JobParametersNotFoundException, + JobRestartException, JobExecutionAlreadyRunningException, JobInstanceAlreadyCompleteException; boolean stop(Long executionId) throws NoSuchJobExecutionException; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersIncrementerNotFoundException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersNotFoundException.java similarity index 83% rename from spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersIncrementerNotFoundException.java rename to spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersNotFoundException.java index 022cddb09..aa80e52ab 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersIncrementerNotFoundException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersNotFoundException.java @@ -26,12 +26,12 @@ import org.springframework.batch.core.JobParametersIncrementer; * @author Dave Syer * */ -public class JobParametersIncrementerNotFoundException extends JobExecutionException { +public class JobParametersNotFoundException extends JobExecutionException { /** * Create an exception with the given message. */ - public JobParametersIncrementerNotFoundException(String msg) { + public JobParametersNotFoundException(String msg) { super(msg); } @@ -39,7 +39,7 @@ public class JobParametersIncrementerNotFoundException extends JobExecutionExcep * @param msg The message to send to caller * @param e the cause of the exception */ - public JobParametersIncrementerNotFoundException(String msg, Throwable e) { + public JobParametersNotFoundException(String msg, Throwable e) { super(msg, e); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java new file mode 100644 index 000000000..d31206023 --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java @@ -0,0 +1,327 @@ +/* + * 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.core.launch.support; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +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.JobParametersIncrementer; +import org.springframework.batch.core.UnexpectedJobExecutionException; +import org.springframework.batch.core.configuration.JobLocator; +import org.springframework.batch.core.converter.DefaultJobParametersConverter; +import org.springframework.batch.core.converter.JobParametersConverter; +import org.springframework.batch.core.explore.BatchMetaDataExplorer; +import org.springframework.batch.core.launch.JobInstanceAlreadyExistsException; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.launch.JobOperator; +import org.springframework.batch.core.launch.JobParametersNotFoundException; +import org.springframework.batch.core.launch.NoSuchJobException; +import org.springframework.batch.core.launch.NoSuchJobExecutionException; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.batch.support.PropertiesConverter; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * @author Dave Syer + * + */ +public class SimpleJobOperator implements JobOperator, InitializingBean { + + /** + * + */ + private static final String ILLEGAL_STATE_MSG = "Illegal state (only happens on a race condition): " + + "%s with name=%s and parameters=%s"; + + private JobLocator jobRegistry; + + private BatchMetaDataExplorer batchMetaDataExplorer; + + private JobLauncher jobLauncher; + + private JobParametersConverter jobParametersConverter = new DefaultJobParametersConverter(); + + private final Log logger = LogFactory.getLog(getClass()); + + /** + * Check mandatory properties. + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(jobLauncher, "JobLauncher must be provided"); + Assert.notNull(jobRegistry, "JobLocator must be provided"); + Assert.notNull(batchMetaDataExplorer, "BatchMetaDataExplorer must be provided"); + } + + /** + * Public setter for the {@link JobParametersConverter}. + * @param jobParametersConverter the {@link JobParametersConverter} to set + */ + public void setJobParametersConverter(JobParametersConverter jobParametersConverter) { + this.jobParametersConverter = jobParametersConverter; + } + + /** + * Public setter for the {@link JobLocator}. + * @param jobRegistry the {@link JobLocator} to set + */ + public void setJobLocator(JobLocator jobRegistry) { + this.jobRegistry = jobRegistry; + } + + /** + * Public setter for the {@link BatchMetaDataExplorer}. + * @param batchMetaDataExplorer the {@link BatchMetaDataExplorer} to set + */ + public void setBatchMetaDataExplorer(BatchMetaDataExplorer batchMetaDataExplorer) { + this.batchMetaDataExplorer = batchMetaDataExplorer; + } + + /** + * Public setter for the {@link JobLauncher}. + * @param jobLauncher the {@link JobLauncher} to set + */ + public void setJobLauncher(JobLauncher jobLauncher) { + this.jobLauncher = jobLauncher; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.launch.JobOperator#getExecutions(java. + * lang.Long) + */ + public List getExecutions(Long instanceId) throws NoSuchJobException { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.launch.JobOperator#getJobNames() + */ + public Set getJobNames() { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.launch.JobOperator#getLastInstances(java + * .lang.String, int) + */ + public List getLastInstances(String jobName, int count) throws NoSuchJobException { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.launch.JobOperator#getParameters(java. + * lang.Long) + */ + public String getParameters(Long executionId) throws NoSuchJobExecutionException { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.launch.JobOperator#getRunningExecutions + * (java.lang.String) + */ + public Set getRunningExecutions(String jobName) throws NoSuchJobException { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.launch.JobOperator#getStepExecutionSummaries + * (java.lang.Long) + */ + public Map getStepExecutionSummaries(Long executionId) throws NoSuchJobExecutionException { + // TODO Auto-generated method stub + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.launch.JobOperator#getSummary(java.lang + * .Long) + */ + public String getSummary(Long executionId) throws NoSuchJobExecutionException { + JobExecution jobExecution = batchMetaDataExplorer.getJobExecution(executionId); + if (jobExecution==null) { + throw new NoSuchJobExecutionException(String.format("No job execution with id=%d", executionId)); + } + return jobExecution.toString(); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.launch.JobOperator#resume(java.lang.Long) + */ + public Long resume(Long executionId) throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException, + NoSuchJobException, JobRestartException { + + logger.info("Checking status of job execution with id=" + executionId); + + JobExecution jobExecution = batchMetaDataExplorer.getJobExecution(executionId); + if (jobExecution == null) { + throw new NoSuchJobExecutionException(String.format("No job execution with id=%d", executionId)); + } + + String jobName = jobExecution.getJobInstance().getJobName(); + Job job = jobRegistry.getJob(jobName ); + JobParameters parameters = jobExecution.getJobInstance().getJobParameters(); + + logger.info(String.format("Attempting to resume job with name=%s and parameters=%s", jobName, parameters)); + try { + return jobLauncher.run(job, parameters).getId(); + } + catch (JobExecutionAlreadyRunningException e) { + throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, + "job execution already running", jobName, parameters), e); + } + + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.launch.JobOperator#start(java.lang.String, + * java.lang.String) + */ + public Long start(String jobName, String parameters) throws NoSuchJobException, JobInstanceAlreadyExistsException { + + logger.info("Checking status of job with name=" + jobName); + + JobParameters jobParameters = jobParametersConverter.getJobParameters(PropertiesConverter + .stringToProperties(parameters)); + + if (batchMetaDataExplorer.isJobInstanceExists(jobName, jobParameters)) { + throw new JobInstanceAlreadyExistsException(String.format( + "Cannot start a job instance that already exists with name=%s and parameters=%s", jobName, + parameters)); + } + + Job job = jobRegistry.getJob(jobName); + + logger.info(String.format("Attempting to launch job with name=%s and parameters=%s", jobName, parameters)); + try { + return jobLauncher.run(job, jobParameters).getId(); + } + catch (JobExecutionAlreadyRunningException e) { + throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, + "job execution already running", jobName, parameters), e); + } + catch (JobRestartException e) { + throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job not restartable", + jobName, parameters), e); + } + catch (JobInstanceAlreadyCompleteException e) { + throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job already complete", + jobName, parameters), e); + } + + } + + /* + * (non-Javadoc) + * + * @see JobOperator#startNextInstance(String ) + */ + public Long startNextInstance(String jobName) throws NoSuchJobException, JobParametersNotFoundException, + UnexpectedJobExecutionException { + + logger.info("Locating parameters for next instance of job with name=" + jobName); + + Job job = jobRegistry.getJob(jobName); + List lastInstances = batchMetaDataExplorer.getLastJobInstances(jobName, 1); + + JobParametersIncrementer incrementer = job.getJobParametersIncrementer(); + if (incrementer == null) { + throw new JobParametersNotFoundException("No job parameters incrementer found for job=" + jobName); + } + + JobParameters parameters; + if (lastInstances.isEmpty()) { + parameters = incrementer.getNext(new JobParameters()); + if (parameters == null) { + throw new JobParametersNotFoundException("No bootstrap parameters found for job=" + jobName); + } + } + else { + parameters = incrementer.getNext(lastInstances.get(0).getJobParameters()); + } + + logger.info(String.format("Attempting to launch job with name=%s and parameters=%s", jobName, parameters)); + try { + return jobLauncher.run(job, parameters).getId(); + } + catch (JobExecutionAlreadyRunningException e) { + throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job already running", jobName, + parameters), e); + } + catch (JobRestartException e) { + throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job not restartable", jobName, + parameters), e); + } + catch (JobInstanceAlreadyCompleteException e) { + throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job instance already complete", + jobName, parameters), e); + } + + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.launch.JobOperator#stop(java.lang.Long) + */ + public boolean stop(Long executionId) throws NoSuchJobExecutionException { + throw new UnsupportedOperationException("See BATCH-453 for implementation."); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/JobSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/JobSupport.java index 7440f86da..4cbfbd068 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/JobSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/JobSupport.java @@ -19,10 +19,11 @@ package org.springframework.batch.core.job; import java.util.ArrayList; import java.util.List; -import org.springframework.batch.core.UnexpectedJobExecutionException; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParametersIncrementer; import org.springframework.batch.core.Step; +import org.springframework.batch.core.UnexpectedJobExecutionException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.util.ClassUtils; @@ -88,7 +89,9 @@ public class JobSupport implements BeanNameAware, Job { this.name = name; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.core.domain.IJob#getName() */ public String getName() { @@ -104,7 +107,9 @@ public class JobSupport implements BeanNameAware, Job { this.steps.add(step); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.core.domain.IJob#getStartLimit() */ public int getStartLimit() { @@ -119,21 +124,37 @@ public class JobSupport implements BeanNameAware, Job { this.restartable = restartable; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.core.domain.IJob#isRestartable() */ public boolean isRestartable() { return restartable; } - - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.Job#run(org.springframework.batch.core.domain.JobExecution) + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.domain.Job#run(org.springframework.batch + * .core.domain.JobExecution) */ public void execute(JobExecution execution) throws UnexpectedJobExecutionException { - throw new UnsupportedOperationException("JobSupport does not provide an implementation of run(). Use a smarter subclass."); + throw new UnsupportedOperationException( + "JobSupport does not provide an implementation of run(). Use a smarter subclass."); } public String toString() { return ClassUtils.getShortName(getClass()) + ": [name=" + name + "]"; } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.Job#getJobParametersIncrementer() + */ + public JobParametersIncrementer getJobParametersIncrementer() { + return null; + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersIncrementerNotFoundExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersNotFoundExceptionTests.java similarity index 84% rename from spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersIncrementerNotFoundExceptionTests.java rename to spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersNotFoundExceptionTests.java index 88b3f2a39..d6968f204 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersIncrementerNotFoundExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersNotFoundExceptionTests.java @@ -21,20 +21,20 @@ import org.springframework.batch.core.AbstractExceptionTests; * @author Dave Syer * */ -public class JobParametersIncrementerNotFoundExceptionTests extends AbstractExceptionTests { +public class JobParametersNotFoundExceptionTests extends AbstractExceptionTests { /* (non-Javadoc) * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) */ public Exception getException(String msg) throws Exception { - return new JobParametersIncrementerNotFoundException(msg); + return new JobParametersNotFoundException(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 JobParametersIncrementerNotFoundException(msg, t); + return new JobParametersNotFoundException(msg, t); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java new file mode 100644 index 000000000..d1184bee1 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java @@ -0,0 +1,190 @@ +/* + * 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.core.launch.support; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Collections; +import java.util.Properties; + +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; +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.JobParametersIncrementer; +import org.springframework.batch.core.configuration.JobLocator; +import org.springframework.batch.core.converter.DefaultJobParametersConverter; +import org.springframework.batch.core.explore.BatchMetaDataExplorer; +import org.springframework.batch.core.job.JobSupport; +import org.springframework.batch.core.launch.JobInstanceAlreadyExistsException; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.launch.NoSuchJobException; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRestartException; + +/** + * @author Dave Syer + * + */ +public class SimpleJobOperatorTests { + + private SimpleJobOperator jobOperator; + + protected Job job; + + private BatchMetaDataExplorer batchMetaDataExplorer; + + private JobParameters jobParameters; + + /** + * @throws Exception + * + */ + @Before + public void setUp() throws Exception { + + job = new JobSupport("foo") { + @Override + public JobParametersIncrementer getJobParametersIncrementer() { + return new JobParametersIncrementer() { + public JobParameters getNext(JobParameters parameters) { + return jobParameters; + } + }; + } + }; + + jobOperator = new SimpleJobOperator(); + + jobOperator.setJobLocator(new JobLocator() { + public Job getJob(String name) throws NoSuchJobException { + if (name.equals("foo")) { + return job; + } + throw new NoSuchJobException("foo"); + } + }); + + jobOperator.setJobLauncher(new JobLauncher() { + public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException, + JobRestartException, JobInstanceAlreadyCompleteException { + return new JobExecution(new JobInstance(123L, jobParameters, job.getName()), 999L); + } + }); + + batchMetaDataExplorer = EasyMock.createNiceMock(BatchMetaDataExplorer.class); + + jobOperator.setBatchMetaDataExplorer(batchMetaDataExplorer); + + jobOperator.setJobParametersConverter(new DefaultJobParametersConverter() { + @Override + public JobParameters getJobParameters(Properties props) { + assertTrue("Wrong properties",props.containsKey("a")); + return jobParameters; + } + }); + + jobOperator.afterPropertiesSet(); + + } + + @Test + public void testMandatoryProperties() throws Exception { + jobOperator = new SimpleJobOperator(); + try { + jobOperator.afterPropertiesSet(); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + /** + * Test method for + * {@link org.springframework.batch.core.launch.support.SimpleJobOperator#startNextInstance(java.lang.String)} + * . + * @throws Exception + */ + @Test + public void testStartNextInstanceSunnyDay() throws Exception { + final JobParameters jobParameters = new JobParameters(); + batchMetaDataExplorer.getLastJobInstances("foo", 1); + EasyMock.expectLastCall().andReturn(Collections.singletonList(new JobInstance(321L, jobParameters, "foo"))); + EasyMock.replay(batchMetaDataExplorer); + Long value = jobOperator.startNextInstance("foo"); + assertEquals(999, value.longValue()); + EasyMock.verify(batchMetaDataExplorer); + } + + @Test + public void testStartNewInstanceSunnyDay() throws Exception { + jobParameters = new JobParameters(); + batchMetaDataExplorer.isJobInstanceExists("foo", jobParameters); + EasyMock.expectLastCall().andReturn(false); + EasyMock.replay(batchMetaDataExplorer); + Long value = jobOperator.start("foo", "a=b"); + assertEquals(999, value.longValue()); + EasyMock.verify(batchMetaDataExplorer); + } + + @Test + public void testStartNewInstanceAlreadyExists() throws Exception { + jobParameters = new JobParameters(); + batchMetaDataExplorer.isJobInstanceExists("foo", jobParameters); + EasyMock.expectLastCall().andReturn(true); + EasyMock.replay(batchMetaDataExplorer); + try { + jobOperator.start("foo", "a=b"); + fail("Expected JobInstanceAlreadyExistsException"); + } + catch (JobInstanceAlreadyExistsException e) { + // expected + } + EasyMock.verify(batchMetaDataExplorer); + } + + @Test + public void testResumeSunnyDay() throws Exception { + jobParameters = new JobParameters(); + batchMetaDataExplorer.getJobExecution(111L); + EasyMock.expectLastCall().andReturn(new JobExecution(new JobInstance(123L, jobParameters, job.getName()), 111L)); + EasyMock.replay(batchMetaDataExplorer); + Long value = jobOperator.resume(111L); + assertEquals(999, value.longValue()); + EasyMock.verify(batchMetaDataExplorer); + } + + @Test + public void testGetSummarySunnyDay() throws Exception { + jobParameters = new JobParameters(); + batchMetaDataExplorer.getJobExecution(111L); + JobExecution jobExecution = new JobExecution(new JobInstance(123L, jobParameters, job.getName()), 111L); + EasyMock.expectLastCall().andReturn(jobExecution); + EasyMock.replay(batchMetaDataExplorer); + String value = jobOperator.getSummary(111L); + assertEquals(jobExecution.toString(), value); + EasyMock.verify(batchMetaDataExplorer); + } + + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobSupport.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobSupport.java index b4aef23e3..7cfdab45d 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobSupport.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobSupport.java @@ -3,6 +3,7 @@ package org.springframework.batch.integration; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobExecutionException; +import org.springframework.batch.core.JobParametersIncrementer; public class JobSupport implements Job { @@ -24,5 +25,10 @@ public class JobSupport implements Job { // TODO Auto-generated method stub return false; } + + public JobParametersIncrementer getJobParametersIncrementer() { + // TODO Auto-generated method stub + return null; + } } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/JobSupport.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/JobSupport.java index f2454e180..73a959222 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/JobSupport.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/JobSupport.java @@ -21,6 +21,7 @@ import java.util.List; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParametersIncrementer; import org.springframework.batch.core.Step; import org.springframework.batch.core.UnexpectedJobExecutionException; import org.springframework.beans.factory.BeanNameAware; @@ -131,6 +132,13 @@ public class JobSupport implements BeanNameAware, Job { return restartable; } + /* (non-Javadoc) + * @see org.springframework.batch.core.Job#getJobParametersIncrementer() + */ + public JobParametersIncrementer getJobParametersIncrementer() { + return null; + } + /* (non-Javadoc) * @see org.springframework.batch.core.domain.Job#run(org.springframework.batch.core.domain.JobExecution) */