From ce16ad2b03b2370498e192ff7ad48052a4951f77 Mon Sep 17 00:00:00 2001
From: Michael Minella
Date: Tue, 30 Jul 2013 11:00:38 -0500
Subject: [PATCH] BATCH-2007: Added a JobOperator implementation that complies
with JSR-352. * Added JsrJobOperator * Added a ParametersConverter (and
JSR-352 implementation) that converts parameters as specified by the JSR to
JobParameters and back * Added a method to the JobRepository to allow the
direct creation of a JobInstance (since the JSR requires a new instance for
each call to JobOperator#start * Added a base context to be bootstrapped when
the JobOperator is first referenced. It provides things like a
JobRepository, etc.
---
.../StepExecutionSerializationUtilsTests.java | 5 +-
.../batch/core/JobExecution.java | 23 +-
.../batch/core/explore/JobExplorer.java | 33 +-
.../explore/support/SimpleJobExplorer.java | 11 +-
.../batch/core/jsr/JobContext.java | 34 +-
.../batch/core/jsr/JobExecution.java | 34 +-
.../core/jsr/JsrJobParametersConverter.java | 132 +++++
.../batch/core/jsr/ParametersConverter.java | 51 ++
.../batch/core/jsr/SimpleMetric.java | 63 +++
.../batch/core/jsr/StepContext.java | 111 ++++
.../batch/core/jsr/StepExecution.java | 99 ++++
.../batch/core/jsr/launch/JsrJobOperator.java | 472 ++++++++++++++----
.../launch/support/SimpleJobLauncher.java | 21 +-
.../launch/support/SimpleJobOperator.java | 3 +-
.../batch/core/repository/JobRepository.java | 56 ++-
.../repository/dao/JdbcJobExecutionDao.java | 20 +-
.../repository/dao/JdbcJobInstanceDao.java | 18 +
.../core/repository/dao/JobInstanceDao.java | 38 +-
.../repository/dao/MapJobInstanceDao.java | 25 +-
.../support/SimpleJobRepository.java | 36 +-
.../src/main/resources/baseContext.xml | 72 +++
.../src/main/resources/batch-hsql.properties | 19 +
.../src/main/resources/beanRefContext.xml | 30 ++
.../springframework/batch/core/schema-db2.sql | 1 +
.../batch/core/schema-derby.sql | 1 +
.../springframework/batch/core/schema-h2.sql | 1 +
.../batch/core/schema-hsqldb.sql | 1 +
.../batch/core/schema-mysql.sql | 1 +
.../batch/core/schema-oracle10g.sql | 1 +
.../batch/core/schema-postgresql.sql | 1 +
.../batch/core/schema-sqlf.sql | 1 +
.../batch/core/schema-sqlserver.sql | 1 +
.../batch/core/schema-sybase.sql | 1 +
.../batch/core/JobExecutionTests.java | 10 +-
.../batch/core/JobParametersBuilderTests.java | 25 -
.../batch/core/JobParametersTests.java | 15 -
.../batch/core/StepExecutionTests.java | 2 +-
.../xml/AbstractJobParserTests.java | 8 +-
.../configuration/xml/DummyJobRepository.java | 11 +
.../support/SimpleJobExplorerTests.java | 38 +-
.../batch/core/jsr/JobContextTests.java | 9 +-
.../batch/core/jsr/JobExecutionTests.java | 4 +-
.../jsr/JsrJobParametersConverterTests.java | 110 ++++
.../core/jsr/ParametersConverterSupport.java | 40 ++
.../batch/core/jsr/SimpleMetricTests.java | 24 +
.../batch/core/jsr/StepContextTests.java | 94 ++++
.../batch/core/jsr/StepExecutionTests.java | 100 ++++
.../core/jsr/launch/JsrJobOperatorTests.java | 340 +++++++++++++
.../jsr/step/batchlet/RestartBatchlet.java | 23 +
.../support/CommandLineJobRunnerTests.java | 27 +-
.../support/SimpleJobOperatorTests.java | 27 +-
.../repository/dao/AbstractJobDaoTests.java | 4 +-
.../dao/AbstractStepExecutionDaoTests.java | 2 +-
.../dao/JdbcJobInstanceDaoTests.java | 4 +-
.../support/SimpleJobRepositoryTests.java | 6 +-
.../core/scope/context/ChunkContextTests.java | 2 +-
.../core/scope/context/StepContextTests.java | 2 +-
.../batch/core/step/JobRepositorySupport.java | 13 +-
.../step/item/TaskletStepExceptionTests.java | 12 +
.../batch-jobs/jsrJobOperatorTestJob.xml | 6 +
.../jsrJobOperatorTestRestartJob.xml | 6 +
.../src/test/resources/META-INF/batch.xml | 4 +
.../repository/dao/schema-prefix-hsqldb.sql | 1 +
.../batch/test/MetaDataInstanceFactory.java | 2 +-
64 files changed, 2098 insertions(+), 289 deletions(-)
create mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JsrJobParametersConverter.java
create mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/jsr/ParametersConverter.java
create mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/jsr/SimpleMetric.java
create mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/jsr/StepContext.java
create mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/jsr/StepExecution.java
create mode 100644 spring-batch-core/src/main/resources/baseContext.xml
create mode 100644 spring-batch-core/src/main/resources/batch-hsql.properties
create mode 100644 spring-batch-core/src/main/resources/beanRefContext.xml
create mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JsrJobParametersConverterTests.java
create mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/jsr/ParametersConverterSupport.java
create mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/jsr/SimpleMetricTests.java
create mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/jsr/StepContextTests.java
create mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/jsr/StepExecutionTests.java
create mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/jsr/launch/JsrJobOperatorTests.java
create mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/jsr/step/batchlet/RestartBatchlet.java
create mode 100644 spring-batch-core/src/test/resources/META-INF/batch-jobs/jsrJobOperatorTestJob.xml
create mode 100644 spring-batch-core/src/test/resources/META-INF/batch-jobs/jsrJobOperatorTestRestartJob.xml
create mode 100644 spring-batch-core/src/test/resources/META-INF/batch.xml
diff --git a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java
index c2df1a748..ebda63632 100644
--- a/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java
+++ b/spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java
@@ -41,7 +41,7 @@ public class StepExecutionSerializationUtilsTests {
@Test
public void testCycle() throws Exception {
StepExecution stepExecution = new StepExecution("step", new JobExecution(new JobInstance(123L,
- "job"), 321L, new JobParameters()), 11L);
+ "job"), 321L, new JobParameters(), null), 11L);
stepExecution.getExecutionContext().put("foo.bar.spam", 123);
StepExecution result = getCopy(stepExecution);
assertEquals(stepExecution, result);
@@ -58,9 +58,10 @@ public class StepExecutionSerializationUtilsTests {
CompletionService completionService = new ExecutorCompletionService(executor);
for (int i = 0; i < repeats; i++) {
- final JobExecution jobExecution = new JobExecution(new JobInstance(123L, "job"), 321L, new JobParameters());
+ final JobExecution jobExecution = new JobExecution(new JobInstance(123L, "job"), 321L, new JobParameters(), null);
for (int j = 0; j < threads; j++) {
completionService.submit(new Callable() {
+ @Override
public StepExecution call() throws Exception {
final StepExecution stepExecution = jobExecution.createStepExecution("step");
stepExecution.getExecutionContext().put("foo.bar.spam", 123);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java
index ba50b838f..cbc9e8a9c 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java
@@ -62,16 +62,27 @@ public class JobExecution extends Entity {
private transient volatile List failureExceptions = new CopyOnWriteArrayList();
+ private final String jobConfigurationName;
+
/**
* Because a JobExecution isn't valid unless the job is set, this
* constructor is the only valid one from a modeling point of view.
*
* @param job the job of which this execution is a part
*/
- public JobExecution(JobInstance job, Long id, JobParameters jobParameters) {
+ public JobExecution(JobInstance job, Long id, JobParameters jobParameters, String jobConfigurationName) {
super(id);
this.jobInstance = job;
this.jobParameters = jobParameters == null ? new JobParameters() : jobParameters;
+ this.jobConfigurationName = jobConfigurationName;
+ }
+
+ public JobExecution(JobInstance job, JobParameters jobParameters, String jobConfigurationName) {
+ this(job, null, jobParameters, jobConfigurationName);
+ }
+
+ public JobExecution(Long id, JobParameters jobParameters, String jobConfigurationName) {
+ this(null, id, jobParameters, jobConfigurationName);
}
/**
@@ -80,15 +91,15 @@ public class JobExecution extends Entity {
* @param job the enclosing {@link JobInstance}
*/
public JobExecution(JobInstance job, JobParameters jobParameters) {
- this(job, null, jobParameters);
+ this(job, null, jobParameters, null);
}
public JobExecution(Long id, JobParameters jobParameters) {
- this(null, id, jobParameters);
+ this(null, id, jobParameters, null);
}
public JobExecution(Long id) {
- this(null, id, null);
+ this(null, id, null, null);
}
public JobParameters getJobParameters() {
@@ -256,6 +267,10 @@ public class JobExecution extends Entity {
this.createTime = createTime;
}
+ public String getJobConfigurationName() {
+ return this.jobConfigurationName;
+ }
+
/**
* Package private method for re-constituting the step executions from
* existing instances.
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java
index f1d81479d..c94a12741 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2013 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.
@@ -21,15 +21,17 @@ import java.util.Set;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.batch.item.ExecutionContext;
/**
* Entry point for browsing executions of running or historical jobs and steps.
* Since the data may be re-hydrated from persistent storage, it may not contain
* volatile fields that would have been present when the execution was active.
- *
+ *
* @author Dave Syer
- *
+ * @author Michael Minella
+ *
* @since 2.0
*/
public interface JobExplorer {
@@ -37,7 +39,7 @@ public interface JobExplorer {
/**
* Fetch {@link JobInstance} values in descending order of creation (and
* therefore usually of first execution).
- *
+ *
* @param jobName the name of the job to query
* @param start the start index of the instances to return
* @param count the maximum number of instances to return
@@ -51,7 +53,7 @@ public interface JobExplorer {
* the parent {@link JobInstance} and associated {@link ExecutionContext}
* and {@link StepExecution} instances (also including their execution
* contexts).
- *
+ *
* @param executionId the job execution id
* @return the {@link JobExecution} with this id, or null if not found
*/
@@ -62,11 +64,11 @@ public interface JobExplorer {
* {@link JobExecution} id. The execution context for the step should be
* available in the result, and the parent job execution should have its
* primitive properties, but may not contain the job instance information.
- *
+ *
* @param jobExecutionId the parent job execution id
* @param stepExecutionId the step execution id
* @return the {@link StepExecution} with this id, or null if not found
- *
+ *
* @see #getJobExecution(Long)
*/
StepExecution getStepExecution(Long jobExecutionId, Long stepExecutionId);
@@ -82,7 +84,7 @@ public interface JobExplorer {
* executions may not be fully hydrated (e.g. their execution context may be
* missing), depending on the implementation. Use
* {@link #getStepExecution(Long, Long)} to hydrate them in that case.
- *
+ *
* @param jobInstance the {@link JobInstance} to query
* @return the set of all executions for the specified {@link JobInstance}
*/
@@ -93,7 +95,7 @@ public interface JobExplorer {
* not be fully hydrated (e.g. their execution context may be missing),
* depending on the implementation. Use
* {@link #getStepExecution(Long, Long)} to hydrate them in that case.
- *
+ *
* @param jobName the name of the job
* @return the set of running executions for jobs with the specified name
*/
@@ -102,9 +104,20 @@ public interface JobExplorer {
/**
* Query the repository for all unique {@link JobInstance} names (sorted
* alphabetically).
- *
+ *
* @return the set of job names that have been executed
*/
List getJobNames();
+ /**
+ * Query the repository for the number of unique {@link JobInstance}s
+ * associated with the supplied job name.
+ *
+ * @param jobName the name of the job to query for
+ * @return the number of {@link JobInstance}s that exist within the
+ * associated job repository
+ * @throws NoSuchJobException
+ */
+ int getJobInstanceCount(String jobName) throws NoSuchJobException;
+
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java
index 93bad72fa..82479888b 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/SimpleJobExplorer.java
@@ -23,6 +23,7 @@ import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.explore.JobExplorer;
+import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.batch.core.repository.dao.ExecutionContextDao;
import org.springframework.batch.core.repository.dao.JobExecutionDao;
import org.springframework.batch.core.repository.dao.JobInstanceDao;
@@ -33,6 +34,7 @@ import org.springframework.batch.core.repository.dao.StepExecutionDao;
*
* @author Dave Syer
* @author Lucas Ward
+ * @author Michael Minella
*
* @see JobExplorer
* @see JobInstanceDao
@@ -180,6 +182,14 @@ public class SimpleJobExplorer implements JobExplorer {
return jobInstanceDao.getJobNames();
}
+ /* (non-Javadoc)
+ * @see org.springframework.batch.core.explore.JobExplorer#getJobInstanceCount(java.lang.String)
+ */
+ @Override
+ public int getJobInstanceCount(String jobName) throws NoSuchJobException {
+ return jobInstanceDao.getJobInstanceCount(jobName);
+ }
+
/*
* Find all dependencies for a JobExecution, including JobInstance (which
* requires JobParameters) plus StepExecutions
@@ -198,5 +208,4 @@ public class SimpleJobExplorer implements JobExplorer {
stepExecution.setExecutionContext(ecDao.getExecutionContext(stepExecution));
}
}
-
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobContext.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobContext.java
index bb2b79827..42293bc98 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobContext.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobContext.java
@@ -35,56 +35,86 @@ public class JobContext implements javax.batch.runtime.context.JobContext {
private JobExecution jobExecution;
private Object transientUserData;
+ private ParametersConverter jobParametersConverter;
/**
* @param jobExecution for the related job
*/
- public JobContext(JobExecution jobExecution) {
+ public JobContext(JobExecution jobExecution, ParametersConverter jobParametersConverter) {
Assert.notNull(jobExecution, "A JobExecution is required");
+ Assert.notNull(jobParametersConverter, "A ParametersConverter is required");
this.jobExecution = jobExecution;
+ this.jobParametersConverter = jobParametersConverter;
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.context.JobContext#getJobName()
+ */
@Override
public String getJobName() {
return jobExecution.getJobInstance().getJobName();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.context.JobContext#getTransientUserData()
+ */
@Override
public Object getTransientUserData() {
return transientUserData;
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.context.JobContext#setTransientUserData(java.lang.Object)
+ */
@Override
public void setTransientUserData(Object data) {
transientUserData = data;
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.context.JobContext#getInstanceId()
+ */
@Override
public long getInstanceId() {
return jobExecution.getJobInstance().getId();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.context.JobContext#getExecutionId()
+ */
@Override
public long getExecutionId() {
return jobExecution.getId();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.context.JobContext#getProperties()
+ */
@Override
public Properties getProperties() {
- return jobExecution.getJobParameters().toProperties();
+ return jobParametersConverter.convert(this.jobExecution.getJobParameters());
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.context.JobContext#getBatchStatus()
+ */
@Override
public BatchStatus getBatchStatus() {
return jobExecution.getStatus().getBatchStatus();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.context.JobContext#getExitStatus()
+ */
@Override
public String getExitStatus() {
return jobExecution.getExitStatus().getExitCode();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.context.JobContext#setExitStatus(java.lang.String)
+ */
@Override
public void setExitStatus(String status) {
jobExecution.setExitStatus(new ExitStatus(status));
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobExecution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobExecution.java
index b489a30cf..99a4c14cb 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobExecution.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JobExecution.java
@@ -32,57 +32,87 @@ import org.springframework.util.Assert;
public class JobExecution implements javax.batch.runtime.JobExecution {
private org.springframework.batch.core.JobExecution execution;
+ private ParametersConverter parametersConverter;
/**
* @param execution for all information to be delegated from
*/
- public JobExecution(org.springframework.batch.core.JobExecution execution) {
+ public JobExecution(org.springframework.batch.core.JobExecution execution, ParametersConverter parametersConverter) {
Assert.notNull(execution, "A JobExecution is required");
this.execution = execution;
+
+ this.parametersConverter = parametersConverter;
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.JobExecution#getExecutionId()
+ */
@Override
public long getExecutionId() {
return this.execution.getId();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.JobExecution#getJobName()
+ */
@Override
public String getJobName() {
return this.execution.getJobInstance().getJobName();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.JobExecution#getBatchStatus()
+ */
@Override
public BatchStatus getBatchStatus() {
return this.execution.getStatus().getBatchStatus();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.JobExecution#getStartTime()
+ */
@Override
public Date getStartTime() {
return this.execution.getStartTime();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.JobExecution#getEndTime()
+ */
@Override
public Date getEndTime() {
return this.execution.getEndTime();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.JobExecution#getExitStatus()
+ */
@Override
public String getExitStatus() {
return this.execution.getExitStatus().getExitCode();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.JobExecution#getCreateTime()
+ */
@Override
public Date getCreateTime() {
return this.execution.getCreateTime();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.JobExecution#getLastUpdatedTime()
+ */
@Override
public Date getLastUpdatedTime() {
return this.execution.getLastUpdated();
}
+ /* (non-Javadoc)
+ * @see javax.batch.runtime.JobExecution#getJobParameters()
+ */
@Override
public Properties getJobParameters() {
- return this.execution.getJobParameters().toProperties();
+ return parametersConverter.convert(this.execution.getJobParameters());
}
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JsrJobParametersConverter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JsrJobParametersConverter.java
new file mode 100644
index 000000000..a992de933
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/JsrJobParametersConverter.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2013 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.jsr;
+
+import java.util.Map;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.springframework.batch.core.JobParameter;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.JobParametersBuilder;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao;
+import org.springframework.batch.item.database.support.DataFieldMaxValueIncrementerFactory;
+import org.springframework.batch.item.database.support.DefaultDataFieldMaxValueIncrementerFactory;
+import org.springframework.batch.support.DatabaseType;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
+import org.springframework.util.Assert;
+
+/**
+ * Provides default conversion methodology for JSR-352's implementation.
+ *
+ * Since Spring Batch uses job parameters as a way of identifying a job
+ * instance, this converter will add an additional identifying parameter if
+ * it does not exist already in the list. The id for the identifying parameter
+ * will come from the JOB_SEQ sequence as used to generate the unique ids
+ * for BATCH_JOB_INSTANCE records.
+ *
+ * @author Michael Minella
+ * @since 3.0
+ */
+public class JsrJobParametersConverter implements ParametersConverter, InitializingBean {
+
+ public static final String JOB_RUN_ID = "jsr_batch_run_id";
+ public DataFieldMaxValueIncrementer incremeter;
+ public String tablePrefix = AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX;
+ public DataSource dataSource;
+
+ /**
+ * Main constructor.
+ *
+ * @param dataSource used to gain access to the database to get unique ids.
+ */
+ public JsrJobParametersConverter(DataSource dataSource) {
+ Assert.notNull(dataSource, "A DataSource is required");
+ this.dataSource = dataSource;
+ }
+
+ /**
+ * The table prefix used in the current {@link JobRepository}
+ *
+ * @param tablePrefix the table prefix used for the job repository tables
+ */
+ public void setTablePrefix(String tablePrefix) {
+ this.tablePrefix = tablePrefix;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ DataFieldMaxValueIncrementerFactory factory = new DefaultDataFieldMaxValueIncrementerFactory(dataSource);
+
+ this.incremeter = factory.getIncrementer(DatabaseType.fromMetaData(dataSource).name(), tablePrefix + "JOB_SEQ");
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.batch.core.jsr.ParametersConverter#convert(java.util.Properties)
+ */
+ @Override
+ public JobParameters convert(Properties parameters) {
+ JobParametersBuilder builder = new JobParametersBuilder();
+ boolean runIdFound = false;
+
+ if(parameters != null) {
+ for (Map.Entry
- *
+ *
* @param jobParameters the runtime parameters for the job
- *
+ *
* @return a valid {@link JobExecution} for the arguments provided
* @throws JobExecutionAlreadyRunningException if there is a
* {@link JobExecution} already running for the job instance with the
@@ -91,17 +113,17 @@ public interface JobRepository {
* false.
* @throws JobInstanceAlreadyCompleteException if a {@link JobInstance} is
* found and was already completed successfully.
- *
+ *
*/
JobExecution createJobExecution(String jobName, JobParameters jobParameters)
throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException;
/**
* Update the {@link JobExecution} (but not its {@link ExecutionContext}).
- *
+ *
* Preconditions: {@link JobExecution} must contain a valid
* {@link JobInstance} and be saved (have an id assigned).
- *
+ *
* @param jobExecution
*/
void update(JobExecution jobExecution);
@@ -111,9 +133,9 @@ public interface JobRepository {
* be assigned - it is not permitted that an ID be assigned before calling
* this method. Instead, it should be left blank, to be assigned by a
* {@link JobRepository}.
- *
+ *
* Preconditions: {@link StepExecution} must have a valid {@link Step}.
- *
+ *
* @param stepExecution
*/
void add(StepExecution stepExecution);
@@ -122,18 +144,18 @@ public interface JobRepository {
* Save a collection of {@link StepExecution}s and each {@link ExecutionContext}. The
* StepExecution ID will be assigned - it is not permitted that an ID be assigned before calling
* this method. Instead, it should be left blank, to be assigned by {@link JobRepository}.
- *
+ *
* Preconditions: {@link StepExecution} must have a valid {@link Step}.
- *
+ *
* @param stepExecution
*/
void addAll(Collection stepExecutions);
/**
* Update the {@link StepExecution} (but not its {@link ExecutionContext}).
- *
+ *
* Preconditions: {@link StepExecution} must be saved (have an id assigned).
- *
+ *
* @param stepExecution
*/
void update(StepExecution stepExecution);
@@ -141,7 +163,7 @@ public interface JobRepository {
/**
* Persist the updated {@link ExecutionContext}s of the given
* {@link StepExecution}.
- *
+ *
* @param stepExecution
*/
void updateExecutionContext(StepExecution stepExecution);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java
index 1bfda6996..0e7f6bf9c 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java
@@ -63,7 +63,7 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
private static final Log logger = LogFactory.getLog(JdbcJobExecutionDao.class);
private static final String SAVE_JOB_EXECUTION = "INSERT into %PREFIX%JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, "
- + "END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, VERSION, CREATE_TIME, LAST_UPDATED) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ + "END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, VERSION, CREATE_TIME, LAST_UPDATED, JOB_CONFIGURATION_LOCATION) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?";
@@ -72,17 +72,17 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
private static final String UPDATE_JOB_EXECUTION = "UPDATE %PREFIX%JOB_EXECUTION set START_TIME = ?, END_TIME = ?, "
+ " STATUS = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, CREATE_TIME = ?, LAST_UPDATED = ? where JOB_EXECUTION_ID = ? and VERSION = ?";
- private static final String FIND_JOB_EXECUTIONS = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, CREATE_TIME, LAST_UPDATED, VERSION"
+ private static final String FIND_JOB_EXECUTIONS = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, CREATE_TIME, LAST_UPDATED, VERSION, JOB_CONFIGURATION_LOCATION"
+ " from %PREFIX%JOB_EXECUTION where JOB_INSTANCE_ID = ? order by JOB_EXECUTION_ID desc";
- private static final String GET_LAST_EXECUTION = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, CREATE_TIME, LAST_UPDATED, VERSION "
+ private static final String GET_LAST_EXECUTION = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, CREATE_TIME, LAST_UPDATED, VERSION, JOB_CONFIGURATION_LOCATION "
+ "from %PREFIX%JOB_EXECUTION E where JOB_INSTANCE_ID = ? and JOB_EXECUTION_ID in (SELECT max(JOB_EXECUTION_ID) from %PREFIX%JOB_EXECUTION E2 where E2.JOB_INSTANCE_ID = ?)";
- private static final String GET_EXECUTION_BY_ID = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, CREATE_TIME, LAST_UPDATED, VERSION"
+ private static final String GET_EXECUTION_BY_ID = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, CREATE_TIME, LAST_UPDATED, VERSION, JOB_CONFIGURATION_LOCATION"
+ " from %PREFIX%JOB_EXECUTION where JOB_EXECUTION_ID = ?";
private static final String GET_RUNNING_EXECUTIONS = "SELECT E.JOB_EXECUTION_ID, E.START_TIME, E.END_TIME, E.STATUS, E.EXIT_CODE, E.EXIT_MESSAGE, E.CREATE_TIME, E.LAST_UPDATED, E.VERSION, "
- + "E.JOB_INSTANCE_ID from %PREFIX%JOB_EXECUTION E, %PREFIX%JOB_INSTANCE I where E.JOB_INSTANCE_ID=I.JOB_INSTANCE_ID and I.JOB_NAME=? and E.END_TIME is NULL order by E.JOB_EXECUTION_ID desc";
+ + "E.JOB_INSTANCE_ID, E.JOB_CONFIGURATION_LOCATION from %PREFIX%JOB_EXECUTION E, %PREFIX%JOB_INSTANCE I where E.JOB_INSTANCE_ID=I.JOB_INSTANCE_ID and I.JOB_NAME=? and E.END_TIME is NULL order by E.JOB_EXECUTION_ID desc";
private static final String CURRENT_VERSION_JOB_EXECUTION = "SELECT VERSION FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID=?";
@@ -151,12 +151,13 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
Object[] parameters = new Object[] { jobExecution.getId(), jobExecution.getJobId(),
jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(),
jobExecution.getExitStatus().getExitCode(), jobExecution.getExitStatus().getExitDescription(),
- jobExecution.getVersion(), jobExecution.getCreateTime(), jobExecution.getLastUpdated() };
+ jobExecution.getVersion(), jobExecution.getCreateTime(), jobExecution.getLastUpdated(),
+ jobExecution.getJobConfigurationName() };
getJdbcTemplate().update(
getQuery(SAVE_JOB_EXECUTION),
parameters,
new int[] { Types.BIGINT, Types.BIGINT, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR,
- Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP });
+ Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR });
insertJobParameters(jobExecution.getId(), jobExecution.getJobParameters());
}
@@ -405,16 +406,17 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
@Override
public JobExecution mapRow(ResultSet rs, int rowNum) throws SQLException {
Long id = rs.getLong(1);
+ String jobConfigurationLocation = rs.getString(10);
JobExecution jobExecution;
if (jobParameters == null) {
jobParameters = getJobParameters(id);
}
if (jobInstance == null) {
- jobExecution = new JobExecution(id, jobParameters);
+ jobExecution = new JobExecution(id, jobParameters, jobConfigurationLocation);
}
else {
- jobExecution = new JobExecution(jobInstance, id, jobParameters);
+ jobExecution = new JobExecution(jobInstance, id, jobParameters, jobConfigurationLocation);
}
jobExecution.setStartTime(rs.getTimestamp(2));
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java
index 874042341..ddba1ff31 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java
@@ -27,6 +27,7 @@ import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobKeyGenerator;
import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
@@ -61,6 +62,8 @@ JobInstanceDao, InitializingBean {
private static final String FIND_JOBS_WITH_KEY = FIND_JOBS_WITH_NAME
+ " and JOB_KEY = ?";
+ private static final String COUNT_JOBS_WITH_NAME = "SELECT COUNT(*) from %PREFIX%JOB_INSTANCE where JOB_NAME = ?";
+
private static final String FIND_JOBS_WITH_EMPTY_KEY = "SELECT JOB_INSTANCE_ID, JOB_NAME from %PREFIX%JOB_INSTANCE where JOB_NAME = ? and (JOB_KEY = ? OR JOB_KEY is NULL)";
private static final String GET_JOB_FROM_ID = "SELECT JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION from %PREFIX%JOB_INSTANCE where JOB_INSTANCE_ID = ?";
@@ -244,6 +247,21 @@ JobInstanceDao, InitializingBean {
}
}
+ /* (non-Javadoc)
+ * @see org.springframework.batch.core.repository.dao.JobInstanceDao#getJobInstanceCount(java.lang.String)
+ */
+ @Override
+ public int getJobInstanceCount(String jobName) throws NoSuchJobException {
+
+ try {
+ return getJdbcTemplate().queryForInt(
+ getQuery(COUNT_JOBS_WITH_NAME),
+ jobName);
+ } catch (EmptyResultDataAccessException e) {
+ throw new NoSuchJobException("No job instances were found for job name " + jobName);
+ }
+ }
+
/**
* Setter for {@link DataFieldMaxValueIncrementer} to be used when
* generating primary keys for {@link JobInstance} instances.
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java
index e1e3f7033..f5cb89dcf 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2013 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.
@@ -21,25 +21,27 @@ import java.util.List;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.launch.NoSuchJobException;
/**
* Data Access Object for job instances.
- *
+ *
* @author Lucas Ward
* @author Robert Kasanicky
- *
+ * @author Michael Minella
+ *
*/
public interface JobInstanceDao {
/**
* Create a JobInstance with given name and parameters.
- *
+ *
* PreConditions: JobInstance for given name and parameters must not already
* exist
- *
+ *
* PostConditions: A valid job instance will be returned which has been
* persisted and contains an unique Id.
- *
+ *
* @param jobName
* @param jobParameters
* @return JobInstance
@@ -49,7 +51,7 @@ public interface JobInstanceDao {
/**
* Find the job instance that matches the given name and parameters. If no
* matching job instances are found, then returns null.
- *
+ *
* @param jobName the name of the job
* @param jobParameters the parameters with which the job was executed
* @return {@link JobInstance} object matching the job name and
@@ -59,7 +61,7 @@ public interface JobInstanceDao {
/**
* Fetch the job instance with the provided identifier.
- *
+ *
* @param instanceId the job identifier
* @return the job instance with this identifier or null if it doesn't exist
*/
@@ -67,17 +69,17 @@ public interface JobInstanceDao {
/**
* Fetch the JobInstance for the provided JobExecution.
- *
+ *
* @param jobExecution the JobExecution
* @return the JobInstance for the provided execution or null if it doesn't exist.
*/
JobInstance getJobInstance(JobExecution jobExecution);
-
+
/**
* Fetch the last job instances with the provided name, sorted backwards by
* primary key.
- *
- *
+ *
+ *
* @param jobName the job name
* @param start the start index of the instances to return
* @param count the maximum number of objects to return
@@ -92,4 +94,16 @@ public interface JobInstanceDao {
*/
List getJobNames();
+
+ /**
+ * Query the repository for the number of unique {@link JobInstance}s
+ * associated with the supplied job name.
+ *
+ * @param jobName the name of the job to query for
+ * @return the number of {@link JobInstance}s that exist within the
+ * associated job repository
+ * @throws NoSuchJobException
+ */
+ int getJobInstanceCount(String jobName) throws NoSuchJobException;
+
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MapJobInstanceDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MapJobInstanceDao.java
index 6848de662..2da7b7443 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MapJobInstanceDao.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MapJobInstanceDao.java
@@ -29,6 +29,7 @@ import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobKeyGenerator;
import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.util.Assert;
/**
@@ -38,7 +39,6 @@ public class MapJobInstanceDao implements JobInstanceDao {
// JDK6 Make a ConcurrentSkipListSet: tends to add on end
private final Map jobInstances = new ConcurrentHashMap();
- // private final Set jobInstances = new CopyOnWriteArraySet();
private JobKeyGenerator jobKeyGenerator = new DefaultJobKeyGenerator();
@@ -55,14 +55,14 @@ public class MapJobInstanceDao implements JobInstanceDao {
JobInstance jobInstance = new JobInstance(currentId.getAndIncrement(), jobName);
jobInstance.incrementVersion();
- jobInstances.put(jobName + jobKeyGenerator.generateKey(jobParameters), jobInstance);
+ jobInstances.put(jobName + "|" + jobKeyGenerator.generateKey(jobParameters), jobInstance);
return jobInstance;
}
@Override
public JobInstance getJobInstance(String jobName, JobParameters jobParameters) {
- return jobInstances.get(jobName + jobKeyGenerator.generateKey(jobParameters));
+ return jobInstances.get(jobName + "|" + jobKeyGenerator.generateKey(jobParameters));
}
@Override
@@ -113,4 +113,23 @@ public class MapJobInstanceDao implements JobInstanceDao {
return jobExecution.getJobInstance();
}
+ @Override
+ public int getJobInstanceCount(String jobName) throws NoSuchJobException {
+ int count = 0;
+
+ for (Map.Entry instanceEntry : jobInstances.entrySet()) {
+ String key = instanceEntry.getKey();
+ String curJobName = key.substring(0, key.lastIndexOf("|"));
+
+ if(curJobName.equals(jobName)) {
+ count++;
+ }
+ }
+
+ if(count == 0) {
+ throw new NoSuchJobException("No job instances for job name " + jobName + " were found");
+ } else {
+ return count;
+ }
+ }
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java
index a54a95255..e76e0c76c 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java
@@ -122,7 +122,7 @@ public class SimpleJobRepository implements JobRepository {
}
BatchStatus status = execution.getStatus();
- if (status == BatchStatus.COMPLETED || status == BatchStatus.ABANDONED) {
+ if (execution.getJobParameters().getParameters().size() > 0 && (status == BatchStatus.COMPLETED || status == BatchStatus.ABANDONED)) {
throw new JobInstanceAlreadyCompleteException(
"A job instance already exists and is complete for parameters=" + jobParameters
+ ". If you want to run this job again, change the parameters.");
@@ -136,7 +136,7 @@ public class SimpleJobRepository implements JobRepository {
executionContext = new ExecutionContext();
}
- JobExecution jobExecution = new JobExecution(jobInstance, jobParameters);
+ JobExecution jobExecution = new JobExecution(jobInstance, jobParameters, null);
jobExecution.setExecutionContext(executionContext);
jobExecution.setLastUpdated(new Date(System.currentTimeMillis()));
@@ -258,7 +258,7 @@ public class SimpleJobRepository implements JobRepository {
return count;
}
- /*
+ /**
* Check to determine whether or not the JobExecution that is the parent of
* the provided StepExecution has been interrupted. If, after synchronizing
* the status with the database, the status has been updated to STOPPING,
@@ -289,4 +289,34 @@ public class SimpleJobRepository implements JobRepository {
return jobExecution;
}
+
+ @Override
+ public JobInstance createJobInstance(String jobName, JobParameters jobParameters) {
+ Assert.notNull(jobName, "A job name is required to create a JobInstance");
+ Assert.notNull(jobParameters, "Job parameters are required to create a JobInstance");
+
+ JobInstance jobInstance = jobInstanceDao.createJobInstance(jobName, jobParameters);
+
+ return jobInstance;
+ }
+
+ @Override
+ public JobExecution createJobExecution(JobInstance jobInstance,
+ JobParameters jobParameters, String jobConfigurationLocation) {
+
+ Assert.notNull(jobInstance, "A JobInstance is required to associate the JobExecution with");
+ Assert.notNull(jobParameters, "A JobParameters object is required to create a JobExecution");
+
+ JobExecution jobExecution = new JobExecution(jobInstance, jobParameters, jobConfigurationLocation);
+ ExecutionContext executionContext = new ExecutionContext();
+ jobExecution.setExecutionContext(executionContext);
+ jobExecution.setLastUpdated(new Date(System.currentTimeMillis()));
+
+ // Save the JobExecution so that it picks up an ID (useful for clients
+ // monitoring asynchronous executions):
+ jobExecutionDao.saveJobExecution(jobExecution);
+ ecDao.saveExecutionContext(jobExecution);
+
+ return jobExecution;
+ }
}
diff --git a/spring-batch-core/src/main/resources/baseContext.xml b/spring-batch-core/src/main/resources/baseContext.xml
new file mode 100644
index 000000000..c77193bfe
--- /dev/null
+++ b/spring-batch-core/src/main/resources/baseContext.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ classpath:batch-${ENVIRONMENT:hsql}.properties
+
+
+
+
+
+
+
+
diff --git a/spring-batch-core/src/main/resources/batch-hsql.properties b/spring-batch-core/src/main/resources/batch-hsql.properties
new file mode 100644
index 000000000..e9af7f5a7
--- /dev/null
+++ b/spring-batch-core/src/main/resources/batch-hsql.properties
@@ -0,0 +1,19 @@
+# Placeholders batch.*
+# for HSQLDB:
+batch.jdbc.driver=org.hsqldb.jdbcDriver
+batch.jdbc.url=jdbc:hsqldb:mem:testdb;sql.enforce_strict_size=true
+# Override and use this one in for a separate server process so you can inspect
+# the results (or add it to system properties with -D to override at run time).
+# batch.jdbc.url=jdbc:hsqldb:hsql://localhost:9005/samples
+batch.jdbc.user=sa
+batch.jdbc.password=
+batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer
+batch.schema.script=classpath*:/org/springframework/batch/core/schema-hsqldb.sql
+batch.drop.script=classpath*:/org/springframework/batch/core/schema-drop-hsqldb.sql
+batch.business.schema.script=
+batch.jdbc.testWhileIdle=true
+batch.jdbc.validationQuery=
+
+
+# Non-platform dependent settings that you might like to change
+batch.data.source.init=true
diff --git a/spring-batch-core/src/main/resources/beanRefContext.xml b/spring-batch-core/src/main/resources/beanRefContext.xml
new file mode 100644
index 000000000..6c75169c4
--- /dev/null
+++ b/spring-batch-core/src/main/resources/beanRefContext.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+ baseContext.xml
+
+
+
+
+
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-db2.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-db2.sql
index 264b52ad2..1fb37d895 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-db2.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-db2.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR(100) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-derby.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-derby.sql
index 8794edb69..735e8a11d 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-derby.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-derby.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR(100) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-h2.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-h2.sql
index a8bf52427..36c1296c4 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-h2.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-h2.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR(100) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-hsqldb.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-hsqldb.sql
index 5ac3d3544..18e838554 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-hsqldb.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-hsqldb.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR(100) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mysql.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mysql.sql
index 9d7e9009b..19780ceb6 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mysql.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mysql.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR(100) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED DATETIME,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ENGINE=InnoDB;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-oracle10g.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-oracle10g.sql
index 73403b90b..0dc4b2a07 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-oracle10g.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-oracle10g.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR2(100) ,
EXIT_MESSAGE VARCHAR2(2500) ,
LAST_UPDATED TIMESTAMP,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-postgresql.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-postgresql.sql
index d0435b3f8..57dfea1c4 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-postgresql.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-postgresql.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR(100) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sqlf.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sqlf.sql
index 8794edb69..735e8a11d 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sqlf.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sqlf.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR(100) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sqlserver.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sqlserver.sql
index 560a304bb..8bf494709 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sqlserver.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sqlserver.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR(100) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED DATETIME,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sybase.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sybase.sql
index 6f122e523..ce6fb0c2b 100644
--- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sybase.sql
+++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sybase.sql
@@ -19,6 +19,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
EXIT_CODE VARCHAR(100) NULL,
EXIT_MESSAGE VARCHAR(2500) NULL,
LAST_UPDATED DATETIME,
+ JOB_CONFIGURATION_LOCATION VARCHAR(500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionTests.java
index 76cc1c64b..3609e8755 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionTests.java
@@ -35,7 +35,7 @@ import org.springframework.batch.support.SerializationUtils;
public class JobExecutionTests {
private JobExecution execution = new JobExecution(new JobInstance(new Long(11), "foo"),
- new Long(12), new JobParameters());
+ new Long(12), new JobParameters(), null);
@Test
public void testJobExecution() {
@@ -53,6 +53,12 @@ public class JobExecutionTests {
assertEquals(100L, execution.getEndTime().getTime());
}
+ @Test
+ public void testGetJobConfigurationName() {
+ execution = new JobExecution(new JobInstance(null, "foo"), null, "/META-INF/batch-jobs/someJob.xml");
+ assertEquals("/META-INF/batch-jobs/someJob.xml", execution.getJobConfigurationName());
+ }
+
/**
* Test method for
* {@link org.springframework.batch.core.JobExecution#getEndTime()}.
@@ -126,7 +132,7 @@ public class JobExecutionTests {
@Test
public void testGetJobId() {
assertEquals(11, execution.getJobId().longValue());
- execution = new JobExecution(new JobInstance(new Long(23), "testJob"), null, new JobParameters());
+ execution = new JobExecution(new JobInstance(new Long(23), "testJob"), null, new JobParameters(), null);
assertEquals(23, execution.getJobId().longValue());
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java
index bc563f4df..aca692377 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java
@@ -6,7 +6,6 @@ import static org.junit.Assert.assertFalse;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
-import java.util.Properties;
import org.junit.Test;
@@ -21,30 +20,6 @@ public class JobParametersBuilderTests {
Date date = new Date(System.currentTimeMillis());
- @Test
- public void testFromProperties() {
- Properties props = new Properties();
- props.put("SCHEDULE_DATE", date.toString());
- props.put("LONG", "1");
- props.put("STRING", "string value");
-
- JobParametersBuilder builder = new JobParametersBuilder(props);
- JobParameters parameters = builder.toJobParameters();
- assertEquals(date.toString(), parameters.getString("SCHEDULE_DATE"));
- assertEquals("1", parameters.getString("LONG").toString());
- assertEquals("string value", parameters.getString("STRING"));
- assertFalse(parameters.getParameters().get("SCHEDULE_DATE").isIdentifying());
- assertFalse(parameters.getParameters().get("LONG").isIdentifying());
- assertFalse(parameters.getParameters().get("STRING").isIdentifying());
- }
-
- @Test
- public void testFromNullProperties() {
- JobParametersBuilder builder = new JobParametersBuilder((Properties) null);
- JobParameters parameters = builder.toJobParameters();
- assertEquals(0, parameters.getParameters().size());
- }
-
@Test
public void testNonIdentifyingParameters() {
parametersBuilder.addDate("SCHEDULE_DATE", date, false);
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java
index 119584b1a..e7a8c62d7 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java
@@ -10,7 +10,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Properties;
import org.junit.Before;
import org.junit.Test;
@@ -213,18 +212,4 @@ public class JobParametersTests {
public void testDateReturnsNullWhenKeyDoesntExit(){
assertNull(new JobParameters().getDate("keythatdoesntexist"));
}
-
- @Test
- public void testToProperties() {
- Properties results = parameters.toProperties();
-
- assertEquals(results.get("string.key1"), "value1");
- assertEquals(results.get("string.key2"), "value2");
- assertEquals(results.get("long.key1"), "1");
- assertEquals(results.get("long.key2"), "2");
- assertEquals(results.get("double.key1"), "1.1");
- assertEquals(results.get("double.key2"), "2.2");
- assertEquals(results.get("date.key1"), String.valueOf(date1.getTime()));
- assertEquals(results.get("date.key2"), String.valueOf(date2.getTime()));
- }
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/StepExecutionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/StepExecutionTests.java
index 043e60860..f0aa2c80f 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/StepExecutionTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/StepExecutionTests.java
@@ -305,7 +305,7 @@ public class StepExecutionTests {
private StepExecution newStepExecution(Step step, Long jobExecutionId, long stepExecutionId) {
JobInstance job = new JobInstance(3L, "testJob");
- StepExecution execution = new StepExecution(step.getName(), new JobExecution(job, jobExecutionId, new JobParameters()), stepExecutionId);
+ StepExecution execution = new StepExecution(step.getName(), new JobExecution(job, jobExecutionId, new JobParameters(), null), stepExecutionId);
return execution;
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java
index 42a1aeea6..caa1e4209 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java
@@ -22,7 +22,7 @@ import java.util.ArrayList;
import org.junit.Before;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
-import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
@@ -42,7 +42,7 @@ public abstract class AbstractJobParserTests {
@Autowired
private JobRepository jobRepository;
-
+
@Autowired
private MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean;
@@ -59,8 +59,8 @@ public abstract class AbstractJobParserTests {
* @return JobExecution
*/
protected JobExecution createJobExecution() throws JobInstanceAlreadyCompleteException, JobRestartException,
- JobExecutionAlreadyRunningException {
- return jobRepository.createJobExecution(job.getName(), new JobParameters());
+ JobExecutionAlreadyRunningException {
+ return jobRepository.createJobExecution(job.getName(), new JobParametersBuilder().addLong("key1", 1l).toJobParameters());
}
/**
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobRepository.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobRepository.java
index 8a0f04aaa..4497c440f 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobRepository.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobRepository.java
@@ -95,4 +95,15 @@ public class DummyJobRepository implements JobRepository, BeanNameAware {
public void addAll(Collection stepExecutions) {
}
+ @Override
+ public JobInstance createJobInstance(String jobName,
+ JobParameters jobParameters) {
+ return null;
+ }
+
+ @Override
+ public JobExecution createJobExecution(JobInstance jobInstance,
+ JobParameters jobParameters, String jobConfigurationLocation) {
+ return null;
+ }
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java
index a8dfb51ee..312557bae 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2007 the original author or authors.
+ * Copyright 2006-2013 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.
@@ -16,11 +16,11 @@
package org.springframework.batch.core.explore.support;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import java.util.Collections;
@@ -30,6 +30,7 @@ import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.launch.NoSuchJobException;
import org.springframework.batch.core.repository.dao.ExecutionContextDao;
import org.springframework.batch.core.repository.dao.JobExecutionDao;
import org.springframework.batch.core.repository.dao.JobInstanceDao;
@@ -40,7 +41,7 @@ import org.springframework.batch.core.repository.dao.StepExecutionDao;
*
* @author Dave Syer
* @author Will Schipp
- *
+ * @author Michael Minella
*
*/
public class SimpleJobExplorerTests {
@@ -57,7 +58,7 @@ public class SimpleJobExplorerTests {
private ExecutionContextDao ecDao;
- private JobExecution jobExecution = new JobExecution(jobInstance, 1234L, new JobParameters());
+ private JobExecution jobExecution = new JobExecution(jobInstance, 1234L, new JobParameters(), null);
@Before
public void setUp() throws Exception {
@@ -93,13 +94,13 @@ public class SimpleJobExplorerTests {
when(jobInstanceDao.getJobInstance(jobExecution)).thenReturn(jobInstance);
StepExecution stepExecution = jobExecution.createStepExecution("foo");
when(stepExecutionDao.getStepExecution(jobExecution, 123L))
- .thenReturn(stepExecution);
+ .thenReturn(stepExecution);
when(ecDao.getExecutionContext(stepExecution)).thenReturn(null);
stepExecution = jobExplorer.getStepExecution(jobExecution.getId(), 123L);
-
- assertEquals(jobInstance,
- stepExecution.getJobExecution().getJobInstance());
-
+
+ assertEquals(jobInstance,
+ stepExecution.getJobExecution().getJobInstance());
+
verify(jobInstanceDao).getJobInstance(jobExecution);
}
@@ -107,7 +108,7 @@ public class SimpleJobExplorerTests {
public void testGetStepExecutionMissing() throws Exception {
when(jobExecutionDao.getJobExecution(jobExecution.getId())).thenReturn(jobExecution);
when(stepExecutionDao.getStepExecution(jobExecution, 123L))
- .thenReturn(null);
+ .thenReturn(null);
assertNull(jobExplorer.getStepExecution(jobExecution.getId(), 123L));
}
@@ -161,4 +162,17 @@ public class SimpleJobExplorerTests {
jobExplorer.getJobNames();
}
+ @Test
+ public void testGetJobInstanceCount() throws Exception {
+ when(jobInstanceDao.getJobInstanceCount("myJob")).thenReturn(4);
+
+ assertEquals(4, jobExplorer.getJobInstanceCount("myJob"));
+ }
+
+ @Test(expected=NoSuchJobException.class)
+ public void testGetJobInstanceCountException() throws Exception {
+ when(jobInstanceDao.getJobInstanceCount("throwException")).thenThrow(new NoSuchJobException("expected"));
+
+ jobExplorer.getJobInstanceCount("throwException");
+ }
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobContextTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobContextTests.java
index fb6f137c9..d3f364251 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobContextTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobContextTests.java
@@ -24,17 +24,19 @@ public class JobContextTests {
private JobExecution execution;
@Mock
private JobInstance instance;
+ @Mock
+ private ParametersConverter converter;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- context = new JobContext(execution);
+ context = new JobContext(execution, converter);
when(execution.getJobInstance()).thenReturn(instance);
}
@Test(expected=IllegalArgumentException.class)
public void testCreateWithNull() {
- context = new JobContext(null);
+ context = new JobContext(null, null);
}
@Test
@@ -69,8 +71,11 @@ public class JobContextTests {
JobParameters params = new JobParametersBuilder()
.addString("key1", "value1")
.toJobParameters();
+ Properties results = new Properties();
+ results.put("key1", "value1");
when(execution.getJobParameters()).thenReturn(params);
+ when(converter.convert(params)).thenReturn(results);
Properties props = context.getProperties();
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobExecutionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobExecutionTests.java
index 0bb970121..8252028cf 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobExecutionTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JobExecutionTests.java
@@ -34,12 +34,12 @@ public class JobExecutionTests {
execution.setStatus(BatchStatus.FAILED);
execution.setVersion(21);
- adapter = new JobExecution(execution);
+ adapter = new JobExecution(execution, new ParametersConverterSupport());
}
@Test(expected=IllegalArgumentException.class)
public void testCreateWithNull() {
- adapter = new JobExecution(null);
+ adapter = new JobExecution(null, new ParametersConverterSupport());
}
@Test
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JsrJobParametersConverterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JsrJobParametersConverterTests.java
new file mode 100644
index 000000000..24224cb84
--- /dev/null
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JsrJobParametersConverterTests.java
@@ -0,0 +1,110 @@
+package org.springframework.batch.core.jsr;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.sql.DataSource;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.JobParametersBuilder;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+
+public class JsrJobParametersConverterTests {
+
+ private JsrJobParametersConverter converter;
+ private static DataSource dataSource;
+
+ @BeforeClass
+ public static void setupDatabase() {
+ dataSource = new EmbeddedDatabaseBuilder().
+ addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql").
+ addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql").
+ build();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ converter = new JsrJobParametersConverter(dataSource);
+ converter.afterPropertiesSet();
+ }
+
+ @Test
+ public void testNullJobParameters() {
+ Properties props = converter.convert((JobParameters) null);
+ assertNotNull(props);
+ Set> properties = props.entrySet();
+ assertEquals(1, properties.size());
+ assertTrue(props.containsKey(JsrJobParametersConverter.JOB_RUN_ID));
+ }
+
+ @Test
+ public void testStringJobParameters() {
+ JobParameters parameters = new JobParametersBuilder().addString("key", "value", false).toJobParameters();
+ Properties props = converter.convert(parameters);
+ assertNotNull(props);
+ Set> properties = props.entrySet();
+ assertEquals(2, properties.size());
+ assertTrue(props.containsKey(JsrJobParametersConverter.JOB_RUN_ID));
+ assertEquals("value", props.getProperty("key"));
+ }
+
+ @Test
+ public void testNonStringJobParameters() {
+ JobParameters parameters = new JobParametersBuilder().addLong("key", 5l, false).toJobParameters();
+ Properties props = converter.convert(parameters);
+ assertNotNull(props);
+ Set> properties = props.entrySet();
+ assertEquals(2, properties.size());
+ assertTrue(props.containsKey(JsrJobParametersConverter.JOB_RUN_ID));
+ assertEquals("5", props.getProperty("key"));
+ }
+
+ @Test
+ public void testJobParametersWithRunId() {
+ JobParameters parameters = new JobParametersBuilder().addLong("key", 5l, false).addLong(JsrJobParametersConverter.JOB_RUN_ID, 2l).toJobParameters();
+ Properties props = converter.convert(parameters);
+ assertNotNull(props);
+ Set> properties = props.entrySet();
+ assertEquals(2, properties.size());
+ assertEquals("2", props.getProperty(JsrJobParametersConverter.JOB_RUN_ID));
+ assertEquals("5", props.getProperty("key"));
+ }
+
+ @Test
+ public void testNullProperties() {
+ JobParameters parameters = converter.convert((Properties)null);
+ assertNotNull(parameters);
+ assertEquals(1, parameters.getParameters().size());
+ assertTrue(parameters.getParameters().containsKey(JsrJobParametersConverter.JOB_RUN_ID));
+ }
+
+ @Test
+ public void testProperties() {
+ Properties properties = new Properties();
+ properties.put("key", "value");
+ JobParameters parameters = converter.convert(properties);
+ assertEquals(2, parameters.getParameters().size());
+ assertEquals("value", parameters.getString("key"));
+ assertTrue(parameters.getParameters().containsKey(JsrJobParametersConverter.JOB_RUN_ID));
+ }
+
+ @Test
+ public void testPropertiesWithRunId() {
+ Properties properties = new Properties();
+ properties.put("key", "value");
+ properties.put(JsrJobParametersConverter.JOB_RUN_ID, "3");
+ JobParameters parameters = converter.convert(properties);
+ assertEquals(2, parameters.getParameters().size());
+ assertEquals("value", parameters.getString("key"));
+ assertEquals(Long.valueOf(3l), parameters.getLong(JsrJobParametersConverter.JOB_RUN_ID));
+ assertTrue(parameters.getParameters().get(JsrJobParametersConverter.JOB_RUN_ID).isIdentifying());
+ }
+}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/ParametersConverterSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/ParametersConverterSupport.java
new file mode 100644
index 000000000..3e3e0210e
--- /dev/null
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/ParametersConverterSupport.java
@@ -0,0 +1,40 @@
+package org.springframework.batch.core.jsr;
+
+import java.util.Map;
+import java.util.Properties;
+
+import org.springframework.batch.core.JobParameter;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.JobParametersBuilder;
+
+public class ParametersConverterSupport implements ParametersConverter {
+
+ @Override
+ public JobParameters convert(Properties parameters) {
+ JobParametersBuilder builder = new JobParametersBuilder();
+
+ if(parameters != null) {
+ for (Map.Entry