IN PROGRESS - issue BATCH-340: Refactor JobRepository for greater clarity and consistency.
http://jira.springframework.org/browse/BATCH-340 JobDao split into JobInstanceDao and JobExecutionDao
This commit is contained in:
@@ -32,6 +32,8 @@ import org.springframework.batch.core.repository.BatchRestartException;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.execution.repository.dao.JobDao;
|
||||
import org.springframework.batch.execution.repository.dao.JobExecutionDao;
|
||||
import org.springframework.batch.execution.repository.dao.JobInstanceDao;
|
||||
import org.springframework.batch.execution.repository.dao.StepExecutionDao;
|
||||
import org.springframework.batch.execution.repository.dao.StepInstanceDao;
|
||||
import org.springframework.batch.item.ExecutionAttributes;
|
||||
@@ -55,7 +57,9 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class SimpleJobRepository implements JobRepository {
|
||||
|
||||
private JobDao jobDao;
|
||||
private JobInstanceDao jobDao;
|
||||
|
||||
private JobExecutionDao jobExecutionDao;
|
||||
|
||||
private StepInstanceDao stepInstanceDao;
|
||||
|
||||
@@ -68,9 +72,11 @@ public class SimpleJobRepository implements JobRepository {
|
||||
SimpleJobRepository() {
|
||||
}
|
||||
|
||||
public SimpleJobRepository(JobDao jobDao, StepInstanceDao stepInstanceDao, StepExecutionDao stepExecutionDao) {
|
||||
public SimpleJobRepository(JobInstanceDao jobDao, JobExecutionDao jobExecutionDao, StepInstanceDao stepInstanceDao,
|
||||
StepExecutionDao stepExecutionDao) {
|
||||
super();
|
||||
this.jobDao = jobDao;
|
||||
this.jobExecutionDao = jobExecutionDao;
|
||||
this.stepInstanceDao = stepInstanceDao;
|
||||
this.stepExecutionDao = stepExecutionDao;
|
||||
}
|
||||
@@ -166,11 +172,11 @@ public class SimpleJobRepository implements JobRepository {
|
||||
// One job was found
|
||||
jobInstance = (JobInstance) jobs.get(0);
|
||||
jobInstance.setStepInstances(findStepInstances(job.getSteps(), jobInstance));
|
||||
jobInstance.setJobExecutionCount(jobDao.getJobExecutionCount(jobInstance.getId()));
|
||||
jobInstance.setJobExecutionCount(jobExecutionDao.getJobExecutionCount(jobInstance.getId()));
|
||||
if (jobInstance.getJobExecutionCount() > job.getStartLimit()) {
|
||||
throw new BatchRestartException("Restart Max exceeded for Job: " + jobInstance.toString());
|
||||
}
|
||||
List executions = jobDao.findJobExecutions(jobInstance);
|
||||
List executions = jobExecutionDao.findJobExecutions(jobInstance);
|
||||
for (Iterator iterator = executions.iterator(); iterator.hasNext();) {
|
||||
JobExecution execution = (JobExecution) iterator.next();
|
||||
if (execution.isRunning()) {
|
||||
@@ -219,11 +225,11 @@ public class SimpleJobRepository implements JobRepository {
|
||||
|
||||
if (jobExecution.getId() == null) {
|
||||
// existing instance
|
||||
jobDao.saveJobExecution(jobExecution);
|
||||
jobExecutionDao.saveJobExecution(jobExecution);
|
||||
}
|
||||
else {
|
||||
// new execution
|
||||
jobDao.updateJobExecution(jobExecution);
|
||||
jobExecutionDao.updateJobExecution(jobExecution);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,504 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.batch.core.repository.NoSuchBatchDomainObjectException;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jdbc implementation of {@link JobDao}. Uses sequences (via Spring's
|
||||
* {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys
|
||||
* before inserting a new row. Objects are checked to ensure all mandatory
|
||||
* fields to be stored are not null. If any are found to be null, an
|
||||
* IllegalArgumentException will be thrown. This could be left to JdbcTemplate,
|
||||
* however, the exception will be fairly vague, and fails to highlight which
|
||||
* field caused the exception.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class JdbcJobDao extends AbstractJdbcBatchMetadataDao implements JobDao, InitializingBean {
|
||||
|
||||
private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?";
|
||||
|
||||
// Job SQL statements
|
||||
private static final String CREATE_JOB = "INSERT into %PREFIX%JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY)"
|
||||
+ " values (?, ?, ?)";
|
||||
|
||||
private static final String CREATE_JOB_PARAMETERS = "INSERT into %PREFIX%JOB_PARAMS(JOB_INSTANCE_ID, KEY_NAME, TYPE_CD, " +
|
||||
"STRING_VAL, DATE_VAL, LONG_VAL) values (?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final int EXIT_MESSAGE_LENGTH = 250;
|
||||
|
||||
private static final String FIND_JOBS = "SELECT JOB_INSTANCE_ID, LAST_JOB_EXECUTION_ID from %PREFIX%JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?";
|
||||
|
||||
private static final String GET_JOB_EXECUTION_COUNT = "SELECT count(JOB_EXECUTION_ID) from %PREFIX%JOB_EXECUTION "
|
||||
+ "where JOB_INSTANCE_ID = ?";
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(JdbcJobDao.class);
|
||||
|
||||
private static final String SAVE_JOB_EXECUTION = "INSERT into %PREFIX%JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, "
|
||||
+ "END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) values (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String UPDATE_JOB = "UPDATE %PREFIX%JOB_INSTANCE set LAST_JOB_EXECUTION_ID = ? where JOB_INSTANCE_ID = ?";
|
||||
|
||||
// Job Execution SqlStatements
|
||||
private static final String UPDATE_JOB_EXECUTION = "UPDATE %PREFIX%JOB_EXECUTION set START_TIME = ?, END_TIME = ?, "
|
||||
+ " STATUS = ?, CONTINUABLE = ?, EXIT_CODE = ?, EXIT_MESSAGE = ? where JOB_EXECUTION_ID = ?";
|
||||
|
||||
private DataFieldMaxValueIncrementer jobExecutionIncrementer;
|
||||
|
||||
private DataFieldMaxValueIncrementer jobIncrementer;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*
|
||||
* Ensure jdbcTemplate and incrementers have been provided.
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(jobIncrementer, "JobIncrementor cannot be null");
|
||||
Assert.notNull(jobExecutionIncrementer,
|
||||
"JobExecutionIncrementer cannot be null");
|
||||
}
|
||||
|
||||
/**
|
||||
* In this sql implementation a job id is obtained by asking the
|
||||
* jobIncrementer (which is likely a sequence) for the nextLong, and then
|
||||
* passing the Id and identifier values (job name, jobKey, schedule date)
|
||||
* into an INSERT statement.
|
||||
*
|
||||
* @see JobDao#createJob(JobIdentifier)
|
||||
* @throws IllegalArgumentException
|
||||
* if any {@link JobIdentifier} fields are null.
|
||||
*/
|
||||
public JobInstance createJobInstance(String jobName, JobParameters jobParameters) {
|
||||
|
||||
Assert.notNull(jobName, "Job Name must not be null.");
|
||||
Assert.notNull(jobParameters, "JobParameters must not be null.");
|
||||
|
||||
Long jobId = new Long(jobIncrementer.nextLongValue());
|
||||
Object[] parameters = new Object[] { jobId, jobName, createJobKey(jobParameters) };
|
||||
getJdbcTemplate().update(getCreateJobQuery(), parameters, new int[] {
|
||||
Types.INTEGER, Types.VARCHAR, Types.VARCHAR});
|
||||
|
||||
insertJobParameters(jobId, jobParameters);
|
||||
|
||||
JobInstance jobInstance = new JobInstance(jobId, jobParameters);
|
||||
return jobInstance;
|
||||
}
|
||||
|
||||
private String createJobKey(JobParameters jobParameters){
|
||||
|
||||
Map props = jobParameters.getParameters();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for(Iterator it = props.entrySet().iterator();it.hasNext();){
|
||||
Entry entry = (Entry)it.next();
|
||||
stringBuilder.append(entry.toString() + ";");
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public List findJobExecutions(final JobInstance job) {
|
||||
|
||||
Assert.notNull(job, "Job cannot be null.");
|
||||
Assert.notNull(job.getId(), "Job Id cannot be null.");
|
||||
|
||||
return getJdbcTemplate().query(
|
||||
getQuery(JobExecutionRowMapper.FIND_JOB_EXECUTIONS),
|
||||
new Object[] { job.getId() }, new JobExecutionRowMapper(job));
|
||||
}
|
||||
|
||||
public JobExecution getJobExecution(Long jobExecutionId) {
|
||||
|
||||
Assert.notNull(jobExecutionId, "Job Execution id must not be null.");
|
||||
|
||||
List executions = getJdbcTemplate().query(
|
||||
getQuery(JobExecutionRowMapper.GET_JOB_EXECUTION),
|
||||
new Object[] { jobExecutionId }, new JobExecutionRowMapper(null));
|
||||
|
||||
JobExecution jobExecution;
|
||||
if(executions.size() == 1){
|
||||
jobExecution = (JobExecution)executions.get(0);
|
||||
}
|
||||
else if(executions.size() == 0){
|
||||
jobExecution = null;
|
||||
}
|
||||
else{
|
||||
throw new IncorrectResultSizeDataAccessException("Only one JobExecution may exist for given id: [" +
|
||||
jobExecutionId + "]", 1, executions.size());
|
||||
}
|
||||
|
||||
return jobExecution;
|
||||
}
|
||||
|
||||
/**
|
||||
* The job table is queried for <strong>any</strong> jobs that match the
|
||||
* given identifier, adding them to a list via the RowMapper callback.
|
||||
*
|
||||
* @see JobDao#findJobInstances(JobIdentifier)
|
||||
* @throws IllegalArgumentException
|
||||
* if any {@link JobIdentifier} fields are null.
|
||||
*/
|
||||
public List findJobInstances(final String jobName, final JobParameters jobParameters) {
|
||||
|
||||
Assert.notNull(jobName, "Job Name must not be null.");
|
||||
Assert.notNull(jobParameters, "JobParameters must not be null.");
|
||||
|
||||
Object[] parameters = new Object[] { jobName,
|
||||
createJobKey(jobParameters) };
|
||||
|
||||
RowMapper rowMapper = new RowMapper() {
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
|
||||
JobInstance jobInstance = new JobInstance(new Long(rs.getLong(1)), jobParameters);
|
||||
long lastExecutionId = rs.getLong(2);
|
||||
JobExecution lastExecution = getJobExecution(new Long(lastExecutionId));
|
||||
if(lastExecution != null){
|
||||
lastExecution.setJobInstance(jobInstance);
|
||||
}
|
||||
jobInstance.setLastExecution(lastExecution);
|
||||
return jobInstance;
|
||||
}
|
||||
};
|
||||
|
||||
return getJdbcTemplate().query(getFindJobsQuery(), parameters, rowMapper);
|
||||
}
|
||||
|
||||
private String getCheckJobExecutionExistsQuery() {
|
||||
return getQuery(CHECK_JOB_EXECUTION_EXISTS);
|
||||
}
|
||||
|
||||
private String getCreateJobQuery() {
|
||||
return getQuery(CREATE_JOB);
|
||||
}
|
||||
|
||||
private String getFindJobsQuery() {
|
||||
return getQuery(FIND_JOBS);
|
||||
}
|
||||
|
||||
private String getCreateJobParamsQuery(){
|
||||
return getQuery(CREATE_JOB_PARAMETERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see JobDao#getJobExecutionCount(JobInstance)
|
||||
* @throws IllegalArgumentException
|
||||
* if jobId is null.
|
||||
*/
|
||||
public int getJobExecutionCount(Long jobId) {
|
||||
|
||||
Assert.notNull(jobId, "JobId cannot be null");
|
||||
|
||||
Object[] parameters = new Object[] { jobId };
|
||||
|
||||
return getJdbcTemplate()
|
||||
.queryForInt(getJobExecutionCountQuery(), parameters);
|
||||
}
|
||||
|
||||
private String getJobExecutionCountQuery() {
|
||||
return getQuery(GET_JOB_EXECUTION_COUNT);
|
||||
}
|
||||
|
||||
private String getSaveJobExecutionQuery() {
|
||||
return getQuery(SAVE_JOB_EXECUTION);
|
||||
}
|
||||
|
||||
private String getUpdateJobExecutionQuery() {
|
||||
return getQuery(UPDATE_JOB_EXECUTION);
|
||||
}
|
||||
|
||||
private String getUpdateJobQuery() {
|
||||
return getQuery(UPDATE_JOB);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience method that inserts all parameters from the provided JobParameters.
|
||||
*
|
||||
*/
|
||||
private void insertJobParameters(Long jobId, JobParameters jobParameters){
|
||||
|
||||
Map parameters = jobParameters.getStringParameters();
|
||||
|
||||
if(!parameters.isEmpty()){
|
||||
for(Iterator it = parameters.entrySet().iterator(); it.hasNext();){
|
||||
Entry entry = (Entry)it.next();
|
||||
insertParameter(jobId, ParameterType.STRING, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getLongParameters();
|
||||
|
||||
if(!parameters.isEmpty()){
|
||||
for(Iterator it = parameters.entrySet().iterator(); it.hasNext();){
|
||||
Entry entry = (Entry)it.next();
|
||||
insertParameter(jobId, ParameterType.LONG, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getDateParameters();
|
||||
|
||||
if(!parameters.isEmpty()){
|
||||
for(Iterator it = parameters.entrySet().iterator(); it.hasNext();){
|
||||
Entry entry = (Entry)it.next();
|
||||
insertParameter(jobId, ParameterType.DATE, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience method that inserts an individual records into the JobParameters table.
|
||||
*/
|
||||
private void insertParameter(Long jobId, ParameterType type, String key, Object value){
|
||||
|
||||
Object[] args = new Object[0];
|
||||
int[] argTypes = new int[]{Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP, Types.INTEGER};
|
||||
|
||||
if(type == ParameterType.STRING){
|
||||
args = new Object[]{jobId, key, type, value, new Timestamp(0L), new Long(0)};
|
||||
}
|
||||
else if(type == ParameterType.LONG){
|
||||
args = new Object[]{jobId, key, type, "", new Timestamp(0L), value};
|
||||
}
|
||||
else if(type == ParameterType.DATE){
|
||||
args = new Object[]{jobId, key, type, "", value, new Long(0)};
|
||||
}
|
||||
|
||||
getJdbcTemplate().update(getCreateJobParamsQuery(), args, argTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* SQL implementation using Sequences via the Spring incrementer
|
||||
* abstraction. Once a new id has been obtained, the JobExecution is saved
|
||||
* via a SQL INSERT statement.
|
||||
*
|
||||
* @see JobDao#saveJobExecution(JobExecution)
|
||||
* @throws IllegalArgumentException
|
||||
* if jobExecution is null, as well as any of it's fields to be
|
||||
* persisted.
|
||||
*/
|
||||
public void saveJobExecution(JobExecution jobExecution) {
|
||||
|
||||
validateJobExecution(jobExecution);
|
||||
|
||||
jobExecution.setId(new Long(jobExecutionIncrementer.nextLongValue()));
|
||||
Object[] parameters = new Object[] { jobExecution.getId(),
|
||||
jobExecution.getJobId(), jobExecution.getStartTime(),
|
||||
jobExecution.getEndTime(), jobExecution.getStatus().toString(),
|
||||
jobExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
jobExecution.getExitStatus().getExitCode(),
|
||||
jobExecution.getExitStatus().getExitDescription() };
|
||||
getJdbcTemplate().update(getSaveJobExecutionQuery(), parameters, new int[] {
|
||||
Types.INTEGER, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP,
|
||||
Types.VARCHAR, Types.CHAR, Types.VARCHAR, Types.VARCHAR });
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for {@link DataFieldMaxValueIncrementer} to be used when
|
||||
* generating primary keys for {@link JobExecution} instances.
|
||||
*
|
||||
* @param jobExecutionIncrementer
|
||||
* the {@link DataFieldMaxValueIncrementer}
|
||||
*/
|
||||
public void setJobExecutionIncrementer(
|
||||
DataFieldMaxValueIncrementer jobExecutionIncrementer) {
|
||||
this.jobExecutionIncrementer = jobExecutionIncrementer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for {@link DataFieldMaxValueIncrementer} to be used when
|
||||
* generating primary keys for {@link JobInstance} instances.
|
||||
*
|
||||
* @param jobIncrementer
|
||||
* the {@link DataFieldMaxValueIncrementer}
|
||||
*/
|
||||
public void setJobIncrementer(DataFieldMaxValueIncrementer jobIncrementer) {
|
||||
this.jobIncrementer = jobIncrementer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update given JobExecution using a SQL UPDATE statement. The JobExecution
|
||||
* is first checked to ensure all fields are not null, and that it has an
|
||||
* ID. The database is then queried to ensure that the ID exists, which
|
||||
* ensures that it is valid.
|
||||
*
|
||||
* @see JobDao#updateJobExecution(JobExecution)
|
||||
*/
|
||||
public void updateJobExecution(JobExecution jobExecution) {
|
||||
|
||||
validateJobExecution(jobExecution);
|
||||
|
||||
String exitDescription = jobExecution.getExitStatus()
|
||||
.getExitDescription();
|
||||
if (exitDescription != null
|
||||
&& exitDescription.length() > EXIT_MESSAGE_LENGTH) {
|
||||
exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH);
|
||||
logger
|
||||
.debug("Truncating long message before update of JobExecution: "
|
||||
+ jobExecution);
|
||||
}
|
||||
Object[] parameters = new Object[] { jobExecution.getStartTime(),
|
||||
jobExecution.getEndTime(), jobExecution.getStatus().toString(),
|
||||
jobExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
jobExecution.getExitStatus().getExitCode(), exitDescription,
|
||||
jobExecution.getId() };
|
||||
|
||||
if (jobExecution.getId() == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"JobExecution ID cannot be null. JobExecution must be saved "
|
||||
+ "before it can be updated.");
|
||||
}
|
||||
|
||||
// Check if given JobExecution's Id already exists, if none is found it
|
||||
// is invalid and
|
||||
// an exception should be thrown.
|
||||
if (getJdbcTemplate().queryForInt(getCheckJobExecutionExistsQuery(),
|
||||
new Object[] { jobExecution.getId() }) != 1) {
|
||||
throw new NoSuchBatchDomainObjectException(
|
||||
"Invalid JobExecution, ID " + jobExecution.getId()
|
||||
+ " not found.");
|
||||
}
|
||||
|
||||
getJdbcTemplate()
|
||||
.update(getUpdateJobExecutionQuery(), parameters,
|
||||
new int[] { Types.TIMESTAMP, Types.TIMESTAMP,
|
||||
Types.VARCHAR, Types.CHAR, Types.VARCHAR,
|
||||
Types.VARCHAR, Types.INTEGER });
|
||||
}
|
||||
|
||||
/**
|
||||
* @see JobDao#updateJobInstance(JobInstance)
|
||||
* @throws IllegalArgumentException
|
||||
* if Job, Job.status, or job.id is null
|
||||
*/
|
||||
public void updateJobInstance(JobInstance jobInstance) {
|
||||
|
||||
Assert.notNull(jobInstance, "Job Cannot be Null");
|
||||
Assert.notNull(jobInstance.getId(), "Job ID cannot be null");
|
||||
|
||||
Long lastExecutionId = jobInstance.getLastExecution() == null ? null : jobInstance.getLastExecution().getId();
|
||||
Object[] parameters = new Object[] { lastExecutionId, jobInstance.getId() };
|
||||
getJdbcTemplate().update(getUpdateJobQuery(), parameters, new int[] {
|
||||
Types.INTEGER, Types.INTEGER});
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate JobExecution. At a minimum, JobId, StartTime, EndTime, and
|
||||
* Status cannot be null.
|
||||
*
|
||||
* @param jobExecution @throws IllegalArgumentException
|
||||
*/
|
||||
private void validateJobExecution(JobExecution jobExecution) {
|
||||
|
||||
Assert.notNull(jobExecution);
|
||||
Assert.notNull(jobExecution.getJobId(),
|
||||
"JobExecution Job-Id cannot be null.");
|
||||
Assert.notNull(jobExecution.getStartTime(),
|
||||
"JobExecution start time cannot be null.");
|
||||
Assert.notNull(jobExecution.getStatus(),
|
||||
"JobExecution status cannot be null.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-usable mapper for {@link JobExecution} instances.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public static class JobExecutionRowMapper implements RowMapper {
|
||||
|
||||
public static final String FIND_JOB_EXECUTIONS = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION"
|
||||
+ " where JOB_INSTANCE_ID = ?";
|
||||
|
||||
public static final String GET_JOB_EXECUTION = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION"
|
||||
+ " where JOB_EXECUTION_ID = ?";
|
||||
|
||||
private JobInstance job;
|
||||
|
||||
public JobExecutionRowMapper(JobInstance job) {
|
||||
super();
|
||||
this.job = job;
|
||||
}
|
||||
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
JobExecution jobExecution = new JobExecution(job);
|
||||
jobExecution.setId(new Long(rs.getLong(1)));
|
||||
jobExecution.setStartTime(rs.getTimestamp(2));
|
||||
jobExecution.setEndTime(rs.getTimestamp(3));
|
||||
jobExecution.setStatus(BatchStatus.getStatus(rs.getString(4)));
|
||||
jobExecution.setExitStatus(new ExitStatus("Y".equals(rs
|
||||
.getString(5)), rs.getString(6), rs.getString(7)));
|
||||
return jobExecution;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ParameterType {
|
||||
|
||||
private final String type;
|
||||
|
||||
private ParameterType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return type;
|
||||
}
|
||||
|
||||
public static final ParameterType STRING = new ParameterType("STRING");
|
||||
|
||||
public static final ParameterType DATE = new ParameterType("DATE");
|
||||
|
||||
public static final ParameterType LONG = new ParameterType("LONG");
|
||||
|
||||
private static final ParameterType[] VALUES = {STRING, DATE, LONG};
|
||||
|
||||
public static ParameterType getType(String typeAsString){
|
||||
|
||||
for(int i = 0; i < VALUES.length; i++){
|
||||
if(VALUES[i].toString().equals(typeAsString)){
|
||||
return (ParameterType)VALUES[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.repository.NoSuchBatchDomainObjectException;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jdbc implementation of {@link JobExecutionDao}. Uses sequences (via Spring's
|
||||
* {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys
|
||||
* before inserting a new row. Objects are checked to ensure all mandatory
|
||||
* fields to be stored are not null. If any are found to be null, an
|
||||
* IllegalArgumentException will be thrown. This could be left to JdbcTemplate,
|
||||
* however, the exception will be fairly vague, and fails to highlight which
|
||||
* field caused the exception.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements JobExecutionDao, InitializingBean {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JdbcJobExecutionDao.class);
|
||||
|
||||
private static final int EXIT_MESSAGE_LENGTH = 250;
|
||||
|
||||
private static final String GET_JOB_EXECUTION_COUNT = "SELECT count(JOB_EXECUTION_ID) from %PREFIX%JOB_EXECUTION "
|
||||
+ "where JOB_INSTANCE_ID = ?";
|
||||
|
||||
private static final String SAVE_JOB_EXECUTION = "INSERT into %PREFIX%JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, "
|
||||
+ "END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) values (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?";
|
||||
|
||||
private static final String UPDATE_JOB_EXECUTION = "UPDATE %PREFIX%JOB_EXECUTION set START_TIME = ?, END_TIME = ?, "
|
||||
+ " STATUS = ?, CONTINUABLE = ?, EXIT_CODE = ?, EXIT_MESSAGE = ? where JOB_EXECUTION_ID = ?";
|
||||
|
||||
private DataFieldMaxValueIncrementer jobExecutionIncrementer;
|
||||
|
||||
public List findJobExecutions(final JobInstance job) {
|
||||
|
||||
Assert.notNull(job, "Job cannot be null.");
|
||||
Assert.notNull(job.getId(), "Job Id cannot be null.");
|
||||
|
||||
return getJdbcTemplate().query(getQuery(JobExecutionRowMapper.FIND_JOB_EXECUTIONS),
|
||||
new Object[] { job.getId() }, new JobExecutionRowMapper(job));
|
||||
}
|
||||
|
||||
public JobExecution getJobExecution(Long jobExecutionId) {
|
||||
|
||||
Assert.notNull(jobExecutionId, "Job Execution id must not be null.");
|
||||
|
||||
List executions = getJdbcTemplate().query(getQuery(JobExecutionRowMapper.GET_JOB_EXECUTION),
|
||||
new Object[] { jobExecutionId }, new JobExecutionRowMapper(null));
|
||||
|
||||
JobExecution jobExecution;
|
||||
if (executions.size() == 1) {
|
||||
jobExecution = (JobExecution) executions.get(0);
|
||||
}
|
||||
else if (executions.size() == 0) {
|
||||
jobExecution = null;
|
||||
}
|
||||
else {
|
||||
throw new IncorrectResultSizeDataAccessException("Only one JobExecution may exist for given id: ["
|
||||
+ jobExecutionId + "]", 1, executions.size());
|
||||
}
|
||||
|
||||
return jobExecution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see JobDao#getJobExecutionCount(JobInstance)
|
||||
* @throws IllegalArgumentException
|
||||
* if jobId is null.
|
||||
*/
|
||||
public int getJobExecutionCount(Long jobId) {
|
||||
|
||||
Assert.notNull(jobId, "JobId cannot be null");
|
||||
|
||||
Object[] parameters = new Object[] { jobId };
|
||||
|
||||
return getJdbcTemplate()
|
||||
.queryForInt(getQuery(GET_JOB_EXECUTION_COUNT), parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* SQL implementation using Sequences via the Spring incrementer
|
||||
* abstraction. Once a new id has been obtained, the JobExecution is saved
|
||||
* via a SQL INSERT statement.
|
||||
*
|
||||
* @see JobDao#saveJobExecution(JobExecution)
|
||||
* @throws IllegalArgumentException
|
||||
* if jobExecution is null, as well as any of it's fields to be
|
||||
* persisted.
|
||||
*/
|
||||
public void saveJobExecution(JobExecution jobExecution) {
|
||||
|
||||
validateJobExecution(jobExecution);
|
||||
|
||||
jobExecution.setId(new Long(jobExecutionIncrementer.nextLongValue()));
|
||||
Object[] parameters = new Object[] { jobExecution.getId(),
|
||||
jobExecution.getJobId(), jobExecution.getStartTime(),
|
||||
jobExecution.getEndTime(), jobExecution.getStatus().toString(),
|
||||
jobExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
jobExecution.getExitStatus().getExitCode(),
|
||||
jobExecution.getExitStatus().getExitDescription() };
|
||||
getJdbcTemplate().update(getQuery(SAVE_JOB_EXECUTION), parameters, new int[] {
|
||||
Types.INTEGER, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP,
|
||||
Types.VARCHAR, Types.CHAR, Types.VARCHAR, Types.VARCHAR });
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate JobExecution. At a minimum, JobId, StartTime, EndTime, and
|
||||
* Status cannot be null.
|
||||
*
|
||||
* @param jobExecution @throws IllegalArgumentException
|
||||
*/
|
||||
private void validateJobExecution(JobExecution jobExecution) {
|
||||
|
||||
Assert.notNull(jobExecution);
|
||||
Assert.notNull(jobExecution.getJobId(),
|
||||
"JobExecution Job-Id cannot be null.");
|
||||
Assert.notNull(jobExecution.getStartTime(),
|
||||
"JobExecution start time cannot be null.");
|
||||
Assert.notNull(jobExecution.getStatus(),
|
||||
"JobExecution status cannot be null.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update given JobExecution using a SQL UPDATE statement. The JobExecution
|
||||
* is first checked to ensure all fields are not null, and that it has an
|
||||
* ID. The database is then queried to ensure that the ID exists, which
|
||||
* ensures that it is valid.
|
||||
*
|
||||
* @see JobDao#updateJobExecution(JobExecution)
|
||||
*/
|
||||
public void updateJobExecution(JobExecution jobExecution) {
|
||||
|
||||
validateJobExecution(jobExecution);
|
||||
|
||||
String exitDescription = jobExecution.getExitStatus()
|
||||
.getExitDescription();
|
||||
if (exitDescription != null
|
||||
&& exitDescription.length() > EXIT_MESSAGE_LENGTH) {
|
||||
exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH);
|
||||
logger
|
||||
.debug("Truncating long message before update of JobExecution: "
|
||||
+ jobExecution);
|
||||
}
|
||||
Object[] parameters = new Object[] { jobExecution.getStartTime(),
|
||||
jobExecution.getEndTime(), jobExecution.getStatus().toString(),
|
||||
jobExecution.getExitStatus().isContinuable() ? "Y" : "N",
|
||||
jobExecution.getExitStatus().getExitCode(), exitDescription,
|
||||
jobExecution.getId() };
|
||||
|
||||
if (jobExecution.getId() == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"JobExecution ID cannot be null. JobExecution must be saved "
|
||||
+ "before it can be updated.");
|
||||
}
|
||||
|
||||
// Check if given JobExecution's Id already exists, if none is found it
|
||||
// is invalid and
|
||||
// an exception should be thrown.
|
||||
if (getJdbcTemplate().queryForInt(getQuery(CHECK_JOB_EXECUTION_EXISTS),
|
||||
new Object[] { jobExecution.getId() }) != 1) {
|
||||
throw new NoSuchBatchDomainObjectException(
|
||||
"Invalid JobExecution, ID " + jobExecution.getId()
|
||||
+ " not found.");
|
||||
}
|
||||
|
||||
getJdbcTemplate()
|
||||
.update(getQuery(UPDATE_JOB_EXECUTION), parameters,
|
||||
new int[] { Types.TIMESTAMP, Types.TIMESTAMP,
|
||||
Types.VARCHAR, Types.CHAR, Types.VARCHAR,
|
||||
Types.VARCHAR, Types.INTEGER });
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for {@link DataFieldMaxValueIncrementer} to be used when
|
||||
* generating primary keys for {@link JobExecution} instances.
|
||||
*
|
||||
* @param jobExecutionIncrementer
|
||||
* the {@link DataFieldMaxValueIncrementer}
|
||||
*/
|
||||
public void setJobExecutionIncrementer(
|
||||
DataFieldMaxValueIncrementer jobExecutionIncrementer) {
|
||||
this.jobExecutionIncrementer = jobExecutionIncrementer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(jobExecutionIncrementer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-usable mapper for {@link JobExecution} instances.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public static class JobExecutionRowMapper implements RowMapper {
|
||||
|
||||
public static final String FIND_JOB_EXECUTIONS = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION"
|
||||
+ " where JOB_INSTANCE_ID = ?";
|
||||
|
||||
public static final String GET_JOB_EXECUTION = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION"
|
||||
+ " where JOB_EXECUTION_ID = ?";
|
||||
|
||||
private JobInstance job;
|
||||
|
||||
public JobExecutionRowMapper(JobInstance job) {
|
||||
super();
|
||||
this.job = job;
|
||||
}
|
||||
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
JobExecution jobExecution = new JobExecution(job);
|
||||
jobExecution.setId(new Long(rs.getLong(1)));
|
||||
jobExecution.setStartTime(rs.getTimestamp(2));
|
||||
jobExecution.setEndTime(rs.getTimestamp(3));
|
||||
jobExecution.setStatus(BatchStatus.getStatus(rs.getString(4)));
|
||||
jobExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(5)), rs.getString(6), rs.getString(7)));
|
||||
return jobExecution;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jdbc implementation of {@link JobInstanceDao}. Uses sequences (via Spring's
|
||||
* {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys
|
||||
* before inserting a new row. Objects are checked to ensure all mandatory
|
||||
* fields to be stored are not null. If any are found to be null, an
|
||||
* IllegalArgumentException will be thrown. This could be left to JdbcTemplate,
|
||||
* however, the exception will be fairly vague, and fails to highlight which
|
||||
* field caused the exception.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Dave Syer
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class JdbcJobInstanceDao extends AbstractJdbcBatchMetadataDao implements JobInstanceDao, InitializingBean {
|
||||
|
||||
private static final String CREATE_JOB = "INSERT into %PREFIX%JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY)"
|
||||
+ " values (?, ?, ?)";
|
||||
|
||||
private static final String CREATE_JOB_PARAMETERS = "INSERT into %PREFIX%JOB_PARAMS(JOB_INSTANCE_ID, KEY_NAME, TYPE_CD, "
|
||||
+ "STRING_VAL, DATE_VAL, LONG_VAL) values (?, ?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String FIND_JOBS = "SELECT JOB_INSTANCE_ID, LAST_JOB_EXECUTION_ID from %PREFIX%JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?";
|
||||
|
||||
private static final String UPDATE_JOB = "UPDATE %PREFIX%JOB_INSTANCE set LAST_JOB_EXECUTION_ID = ? where JOB_INSTANCE_ID = ?";
|
||||
|
||||
private DataFieldMaxValueIncrementer jobIncrementer;
|
||||
|
||||
private JobExecutionDao jobExecutionDao;
|
||||
|
||||
/**
|
||||
* In this jdbc implementation a job id is obtained by asking the
|
||||
* jobIncrementer (which is likely a sequence) for the nextLong, and then
|
||||
* passing the Id and parameter values into an INSERT statement.
|
||||
*
|
||||
* @see JobDao#createJob(JobIdentifier)
|
||||
* @throws IllegalArgumentException if any {@link JobIdentifier} fields are
|
||||
* null.
|
||||
*/
|
||||
public JobInstance createJobInstance(String jobName, JobParameters jobParameters) {
|
||||
|
||||
Assert.notNull(jobName, "Job Name must not be null.");
|
||||
Assert.notNull(jobParameters, "JobParameters must not be null.");
|
||||
|
||||
Long jobId = new Long(jobIncrementer.nextLongValue());
|
||||
Object[] parameters = new Object[] { jobId, jobName, createJobKey(jobParameters) };
|
||||
getJdbcTemplate().update(getQuery(CREATE_JOB), parameters,
|
||||
new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR });
|
||||
|
||||
insertJobParameters(jobId, jobParameters);
|
||||
|
||||
JobInstance jobInstance = new JobInstance(jobId, jobParameters);
|
||||
return jobInstance;
|
||||
}
|
||||
|
||||
private String createJobKey(JobParameters jobParameters) {
|
||||
|
||||
Map props = jobParameters.getParameters();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (Iterator it = props.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
stringBuilder.append(entry.toString() + ";");
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that inserts all parameters from the provided
|
||||
* JobParameters.
|
||||
*
|
||||
*/
|
||||
private void insertJobParameters(Long jobId, JobParameters jobParameters) {
|
||||
|
||||
Map parameters = jobParameters.getStringParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.STRING, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getLongParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.LONG, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
parameters = jobParameters.getDateParameters();
|
||||
|
||||
if (!parameters.isEmpty()) {
|
||||
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) {
|
||||
Entry entry = (Entry) it.next();
|
||||
insertParameter(jobId, ParameterType.DATE, entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that inserts an individual records into the
|
||||
* JobParameters table.
|
||||
*/
|
||||
private void insertParameter(Long jobId, ParameterType type, String key, Object value) {
|
||||
|
||||
Object[] args = new Object[0];
|
||||
int[] argTypes = new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP,
|
||||
Types.INTEGER };
|
||||
|
||||
if (type == ParameterType.STRING) {
|
||||
args = new Object[] { jobId, key, type, value, new Timestamp(0L), new Long(0) };
|
||||
}
|
||||
else if (type == ParameterType.LONG) {
|
||||
args = new Object[] { jobId, key, type, "", new Timestamp(0L), value };
|
||||
}
|
||||
else if (type == ParameterType.DATE) {
|
||||
args = new Object[] { jobId, key, type, "", value, new Long(0) };
|
||||
}
|
||||
|
||||
getJdbcTemplate().update(getQuery(CREATE_JOB_PARAMETERS), args, argTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* The job table is queried for <strong>any</strong> jobs that match the
|
||||
* given identifier, adding them to a list via the RowMapper callback.
|
||||
*
|
||||
* @see JobDao#findJobInstances(JobIdentifier)
|
||||
* @throws IllegalArgumentException
|
||||
* if any {@link JobIdentifier} fields are null.
|
||||
*/
|
||||
public List findJobInstances(final String jobName, final JobParameters jobParameters) {
|
||||
|
||||
Assert.notNull(jobName, "Job Name must not be null.");
|
||||
Assert.notNull(jobParameters, "JobParameters must not be null.");
|
||||
|
||||
Object[] parameters = new Object[] { jobName,
|
||||
createJobKey(jobParameters) };
|
||||
|
||||
RowMapper rowMapper = new RowMapper() {
|
||||
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||
|
||||
JobInstance jobInstance = new JobInstance(new Long(rs.getLong(1)), jobParameters);
|
||||
long lastExecutionId = rs.getLong(2);
|
||||
JobExecution lastExecution = jobExecutionDao.getJobExecution(new Long(lastExecutionId));
|
||||
if(lastExecution != null){
|
||||
lastExecution.setJobInstance(jobInstance);
|
||||
}
|
||||
jobInstance.setLastExecution(lastExecution);
|
||||
return jobInstance;
|
||||
}
|
||||
};
|
||||
|
||||
return getJdbcTemplate().query(getQuery(FIND_JOBS), parameters, rowMapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see JobDao#updateJobInstance(JobInstance)
|
||||
* @throws IllegalArgumentException
|
||||
* if Job, Job.status, or job.id is null
|
||||
*/
|
||||
public void updateJobInstance(JobInstance jobInstance) {
|
||||
|
||||
Assert.notNull(jobInstance, "Job Cannot be Null");
|
||||
Assert.notNull(jobInstance.getId(), "Job ID cannot be null");
|
||||
|
||||
Long lastExecutionId = jobInstance.getLastExecution() == null ? null : jobInstance.getLastExecution().getId();
|
||||
Object[] parameters = new Object[] { lastExecutionId, jobInstance.getId() };
|
||||
getJdbcTemplate().update(getQuery(UPDATE_JOB), parameters, new int[] {
|
||||
Types.INTEGER, Types.INTEGER});
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for {@link DataFieldMaxValueIncrementer} to be used when
|
||||
* generating primary keys for {@link JobInstance} instances.
|
||||
*
|
||||
* @param jobIncrementer the {@link DataFieldMaxValueIncrementer}
|
||||
*/
|
||||
public void setJobIncrementer(DataFieldMaxValueIncrementer jobIncrementer) {
|
||||
this.jobIncrementer = jobIncrementer;
|
||||
}
|
||||
|
||||
public void setJobExecutionDao(JobExecutionDao jobExecutionDao) {
|
||||
this.jobExecutionDao = jobExecutionDao;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(jobExecutionDao);
|
||||
Assert.notNull(jobIncrementer);
|
||||
}
|
||||
|
||||
|
||||
private static class ParameterType {
|
||||
|
||||
private final String type;
|
||||
|
||||
private ParameterType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static final ParameterType STRING = new ParameterType("STRING");
|
||||
|
||||
public static final ParameterType DATE = new ParameterType("DATE");
|
||||
|
||||
public static final ParameterType LONG = new ParameterType("LONG");
|
||||
|
||||
private static final ParameterType[] VALUES = { STRING, DATE, LONG };
|
||||
|
||||
public static ParameterType getType(String typeAsString) {
|
||||
|
||||
for (int i = 0; i < VALUES.length; i++) {
|
||||
if (VALUES[i].toString().equals(typeAsString)) {
|
||||
return (ParameterType) VALUES[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import org.springframework.batch.core.domain.BatchStatus;
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.StepExecution;
|
||||
import org.springframework.batch.core.domain.StepInstance;
|
||||
import org.springframework.batch.execution.repository.dao.JdbcJobDao.JobExecutionRowMapper;
|
||||
import org.springframework.batch.execution.repository.dao.JdbcJobExecutionDao.JobExecutionRowMapper;
|
||||
import org.springframework.batch.io.exception.BatchCriticalException;
|
||||
import org.springframework.batch.item.ExecutionAttributes;
|
||||
import org.springframework.batch.repeat.ExitStatus;
|
||||
@@ -91,7 +91,7 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao
|
||||
|
||||
private DataFieldMaxValueIncrementer stepExecutionIncrementer;
|
||||
|
||||
private JobDao jobDao;
|
||||
private JobExecutionDao jobExecutionDao;
|
||||
|
||||
public ExecutionAttributes findExecutionAttributes(final Long executionId) {
|
||||
|
||||
@@ -282,7 +282,7 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao
|
||||
// assume already saved...
|
||||
return;
|
||||
}
|
||||
jobDao.saveJobExecution(jobExecution);
|
||||
jobExecutionDao.saveJobExecution(jobExecution);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -458,13 +458,13 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao
|
||||
this.stepExecutionIncrementer = stepExecutionIncrementer;
|
||||
}
|
||||
|
||||
public void setJobDao(JobDao jobDao) {
|
||||
this.jobDao = jobDao;
|
||||
public void setJobExecutionDao(JobExecutionDao jobExecutionDao) {
|
||||
this.jobExecutionDao = jobExecutionDao;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(stepExecutionIncrementer, "StepExecutionIncrementer cannot be null.");
|
||||
Assert.notNull(jobDao, "JobDao cannot be null");
|
||||
Assert.notNull(jobExecutionDao, "JobDao cannot be null");
|
||||
}
|
||||
|
||||
public static class AttributeType {
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
|
||||
/**
|
||||
* Data Access Object for jobs.
|
||||
@@ -29,84 +23,6 @@ import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public interface JobDao {
|
||||
public interface JobDao extends JobInstanceDao, JobExecutionDao {
|
||||
|
||||
/**
|
||||
* Create a JobInstance with given name and parameters.
|
||||
*
|
||||
* PostConditions: A valid job will be returned which has been persisted and
|
||||
* contains an unique Id.
|
||||
*
|
||||
* @param jobName
|
||||
* @param jobParameters
|
||||
* @return JobInstance
|
||||
*/
|
||||
JobInstance createJobInstance(String jobName, JobParameters jobParameters);
|
||||
|
||||
/**
|
||||
* Find all job instances that match the given name and parameters. If no
|
||||
* matching job instances are found, then a list of size 0 will be
|
||||
* returned.
|
||||
*
|
||||
* @param jobName
|
||||
* @param jobParameters
|
||||
* @return List of {@link JobInstance} objects matching
|
||||
* {@link JobIdentifier}
|
||||
*/
|
||||
List findJobInstances(String jobName, JobParameters jobParameters);
|
||||
|
||||
/**
|
||||
* Update an existing JobInstance.
|
||||
*
|
||||
* Preconditions: jobInstance must have an ID.
|
||||
*
|
||||
* @param jobInstance
|
||||
*/
|
||||
void updateJobInstance(JobInstance jobInstance);
|
||||
|
||||
/**
|
||||
* Save a new JobExecution.
|
||||
*
|
||||
* Preconditions: jobExecution must have a jobInstanceId.
|
||||
*
|
||||
* @param jobExecution
|
||||
*/
|
||||
void saveJobExecution(JobExecution jobExecution);
|
||||
|
||||
/**
|
||||
* Update and existing JobExecution.
|
||||
*
|
||||
* Preconditions: jobExecution must have an Id (which can be obtained by the
|
||||
* save method) and a jobInstanceId.
|
||||
*
|
||||
* @param jobExecution
|
||||
*/
|
||||
void updateJobExecution(JobExecution jobExecution);
|
||||
|
||||
/**
|
||||
* Return the number of JobExecutions with the given jobInstanceId
|
||||
*
|
||||
* Preconditions: jobInstance must have an id.
|
||||
*
|
||||
* @param jobInstanceId
|
||||
*/
|
||||
int getJobExecutionCount(Long jobInstanceId);
|
||||
|
||||
/**
|
||||
* Return list of JobExecutions for given JobInstance.
|
||||
*
|
||||
* @param jobInstance
|
||||
* @return list of jobExecutions.
|
||||
*/
|
||||
List findJobExecutions(JobInstance jobInstance);
|
||||
|
||||
/**
|
||||
* Given an id, return the matching JobExecution.
|
||||
*
|
||||
* @param jobExecutionId - id of the execution to be returned.
|
||||
* @return {@link JobExecution} matching the id.
|
||||
* @throws {@link IncorrectResultSizeDataAccessException} if more than one
|
||||
* execution is found for the given id.
|
||||
*/
|
||||
JobExecution getJobExecution(Long jobExecutionId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.core.domain.JobExecution;
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
|
||||
/**
|
||||
* Data Access Object for job executions.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public interface JobExecutionDao {
|
||||
|
||||
/**
|
||||
* Save a new JobExecution.
|
||||
*
|
||||
* Preconditions: jobExecution must have a jobInstanceId.
|
||||
*
|
||||
* @param jobExecution
|
||||
*/
|
||||
void saveJobExecution(JobExecution jobExecution);
|
||||
|
||||
/**
|
||||
* Update and existing JobExecution.
|
||||
*
|
||||
* Preconditions: jobExecution must have an Id (which can be obtained by the
|
||||
* save method) and a jobInstanceId.
|
||||
*
|
||||
* @param jobExecution
|
||||
*/
|
||||
void updateJobExecution(JobExecution jobExecution);
|
||||
|
||||
/**
|
||||
* Return the number of JobExecutions with the given jobInstanceId
|
||||
*
|
||||
* Preconditions: jobInstance must have an id.
|
||||
*
|
||||
* @param jobInstanceId
|
||||
*/
|
||||
int getJobExecutionCount(Long jobInstanceId);
|
||||
|
||||
/**
|
||||
* Return list of JobExecutions for given JobInstance.
|
||||
*
|
||||
* @param jobInstance
|
||||
* @return list of jobExecutions.
|
||||
*/
|
||||
List findJobExecutions(JobInstance jobInstance);
|
||||
|
||||
/**
|
||||
* Given an id, return the matching JobExecution.
|
||||
*
|
||||
* @param jobExecutionId - id of the execution to be returned.
|
||||
* @return {@link JobExecution} matching the id.
|
||||
* @throws {@link IncorrectResultSizeDataAccessException} if more than one
|
||||
* execution is found for the given id.
|
||||
*/
|
||||
JobExecution getJobExecution(Long jobExecutionId);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.springframework.batch.execution.repository.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.core.domain.JobInstance;
|
||||
import org.springframework.batch.core.domain.JobParameters;
|
||||
|
||||
/**
|
||||
* Data Access Object for job instances.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Robert Kasanicky
|
||||
*
|
||||
*/
|
||||
public interface JobInstanceDao {
|
||||
|
||||
/**
|
||||
* Create a JobInstance with given name and parameters.
|
||||
*
|
||||
* PostConditions: A valid job will be returned which has been persisted and
|
||||
* contains an unique Id.
|
||||
*
|
||||
* @param jobName
|
||||
* @param jobParameters
|
||||
* @return JobInstance
|
||||
*/
|
||||
JobInstance createJobInstance(String jobName, JobParameters jobParameters);
|
||||
|
||||
/**
|
||||
* Find all job instances that match the given name and parameters. If no
|
||||
* matching job instances are found, then a list of size 0 will be
|
||||
* returned.
|
||||
*
|
||||
* @param jobName
|
||||
* @param jobParameters
|
||||
* @return List of {@link JobInstance} objects matching
|
||||
* {@link JobIdentifier}
|
||||
*/
|
||||
List findJobInstances(String jobName, JobParameters jobParameters);
|
||||
|
||||
/**
|
||||
* Update an existing JobInstance.
|
||||
*
|
||||
* Preconditions: jobInstance must have an ID.
|
||||
*
|
||||
* @param jobInstance
|
||||
*/
|
||||
void updateJobInstance(JobInstance jobInstance);
|
||||
}
|
||||
@@ -31,7 +31,8 @@ import org.springframework.batch.core.domain.StepInstance;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier;
|
||||
import org.springframework.batch.execution.repository.SimpleJobRepository;
|
||||
import org.springframework.batch.execution.repository.dao.JobDao;
|
||||
import org.springframework.batch.execution.repository.dao.JobExecutionDao;
|
||||
import org.springframework.batch.execution.repository.dao.JobInstanceDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapJobDao;
|
||||
import org.springframework.batch.execution.repository.dao.MapStepDao;
|
||||
import org.springframework.batch.execution.repository.dao.StepExecutionDao;
|
||||
@@ -51,7 +52,9 @@ public class SimpleJobTests extends TestCase {
|
||||
|
||||
private JobRepository jobRepository;
|
||||
|
||||
private JobDao jobDao;
|
||||
private JobInstanceDao jobInstanceDao;
|
||||
|
||||
private JobExecutionDao jobExecutionDao;
|
||||
|
||||
private StepInstanceDao stepInstanceDao;
|
||||
|
||||
@@ -84,10 +87,11 @@ public class SimpleJobTests extends TestCase {
|
||||
|
||||
MapJobDao.clear();
|
||||
MapStepDao.clear();
|
||||
jobDao = new MapJobDao();
|
||||
jobInstanceDao = new MapJobDao();
|
||||
jobExecutionDao = new MapJobDao();
|
||||
stepInstanceDao = new MapStepDao();
|
||||
stepExecutionDao = new MapStepDao();
|
||||
jobRepository = new SimpleJobRepository(jobDao, stepInstanceDao, stepExecutionDao);
|
||||
jobRepository = new SimpleJobRepository(jobInstanceDao, jobExecutionDao, stepInstanceDao, stepExecutionDao);
|
||||
job = new SimpleJob();
|
||||
job.setJobRepository(jobRepository);
|
||||
|
||||
@@ -254,9 +258,9 @@ public class SimpleJobTests extends TestCase {
|
||||
* Check JobRepository to ensure status is being saved.
|
||||
*/
|
||||
private void checkRepository(BatchStatus status, ExitStatus exitStatus) {
|
||||
assertEquals(jobInstance, jobDao.findJobInstances(jobInstance.getJobName(), jobParameters).get(0));
|
||||
assertEquals(jobInstance, jobInstanceDao.findJobInstances(jobInstance.getJobName(), jobParameters).get(0));
|
||||
// because map dao stores in memory, it can be checked directly
|
||||
JobExecution jobExecution = (JobExecution) jobDao.findJobExecutions(jobInstance).get(0);
|
||||
JobExecution jobExecution = (JobExecution) jobExecutionDao.findJobExecutions(jobInstance).get(0);
|
||||
assertEquals(jobInstance.getId(), jobExecution.getJobId());
|
||||
assertEquals(status, jobExecution.getStatus());
|
||||
if (exitStatus != null) {
|
||||
|
||||
@@ -49,7 +49,7 @@ public class SimpleJobTests extends TestCase {
|
||||
|
||||
private List recovered = new ArrayList();
|
||||
|
||||
private SimpleJobRepository repository = new SimpleJobRepository(new MapJobDao(), new MapStepDao(), new MapStepDao());
|
||||
private SimpleJobRepository repository = new SimpleJobRepository(new MapJobDao(), new MapJobDao(), new MapStepDao(), new MapStepDao());
|
||||
|
||||
private List processed = new ArrayList();
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ public class SimpleJobRepositoryTests extends TestCase {
|
||||
jobDao = (JobDao) jobDaoControl.getMock();
|
||||
stepDao = (StepDao) stepDaoControl.getMock();
|
||||
|
||||
jobRepository = new SimpleJobRepository(jobDao, stepDao, stepDao);
|
||||
jobRepository = new SimpleJobRepository(jobDao, jobDao, stepDao, stepDao);
|
||||
|
||||
jobParameters = new JobParametersBuilder().toJobParameters();
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@ import org.springframework.util.ClassUtils;
|
||||
public abstract class AbstractJobDaoTests extends
|
||||
AbstractTransactionalDataSourceSpringContextTests {
|
||||
|
||||
protected JobDao jobDao;
|
||||
protected JobInstanceDao jobInstanceDao;
|
||||
|
||||
protected JobExecutionDao jobExecutionDao;
|
||||
|
||||
protected JobParameters jobParameters = new JobParametersBuilder().addString("job.key", "jobKey").toJobParameters();
|
||||
|
||||
@@ -61,8 +63,12 @@ public abstract class AbstractJobDaoTests extends
|
||||
* Because AbstractTransactionalSpringContextTests is used, this method will
|
||||
* be called by Spring to set the JobRepository.
|
||||
*/
|
||||
public void setJobRepositoryDao(JobDao jobRepositoryDao) {
|
||||
this.jobDao = jobRepositoryDao;
|
||||
public void setJobInstanceDao(JobInstanceDao jobInstanceDao) {
|
||||
this.jobInstanceDao = jobInstanceDao;
|
||||
}
|
||||
|
||||
public void setJobExecutionDao(JobExecutionDao jobExecutionDao) {
|
||||
this.jobExecutionDao = jobExecutionDao;
|
||||
}
|
||||
|
||||
protected void onSetUpInTransaction() throws Exception {
|
||||
@@ -72,16 +78,16 @@ public abstract class AbstractJobDaoTests extends
|
||||
job = new JobSupport("Job1");
|
||||
|
||||
// Create job.
|
||||
jobInstance = jobDao.createJobInstance(job.getName(), jobParameters);
|
||||
jobInstance = jobInstanceDao.createJobInstance(job.getName(), jobParameters);
|
||||
|
||||
// Create an execution
|
||||
jobExecutionStartTime = new Date(System.currentTimeMillis());
|
||||
jobExecution = new JobExecution(jobInstance);
|
||||
jobExecution.setStartTime(jobExecutionStartTime);
|
||||
jobExecution.setStatus(BatchStatus.STARTED);
|
||||
jobDao.saveJobExecution(jobExecution);
|
||||
jobExecutionDao.saveJobExecution(jobExecution);
|
||||
jobInstance.setLastExecution(jobExecution);
|
||||
jobDao.updateJobInstance(jobInstance);
|
||||
jobInstanceDao.updateJobInstance(jobInstance);
|
||||
}
|
||||
|
||||
public void testVersionIsNotNullForJob() throws Exception {
|
||||
@@ -100,13 +106,13 @@ public abstract class AbstractJobDaoTests extends
|
||||
|
||||
public void testFindNonExistentJob() {
|
||||
// No job should be found since it hasn't been created.
|
||||
List jobs = jobDao.findJobInstances("nonexistentJob", jobParameters);
|
||||
List jobs = jobInstanceDao.findJobInstances("nonexistentJob", jobParameters);
|
||||
assertTrue(jobs.size() == 0);
|
||||
}
|
||||
|
||||
public void testFindJob() {
|
||||
|
||||
List jobs = jobDao.findJobInstances(job.getName(), jobParameters);
|
||||
List jobs = jobInstanceDao.findJobInstances(job.getName(), jobParameters);
|
||||
assertTrue(jobs.size() == 1);
|
||||
JobInstance tempJob = (JobInstance) jobs.get(0);
|
||||
assertTrue(jobInstance.equals(tempJob));
|
||||
@@ -116,7 +122,7 @@ public abstract class AbstractJobDaoTests extends
|
||||
public void testFindJobWithNullRuntime() {
|
||||
|
||||
try {
|
||||
jobDao.findJobInstances(null, null);
|
||||
jobInstanceDao.findJobInstances(null, null);
|
||||
fail();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
@@ -130,7 +136,7 @@ public abstract class AbstractJobDaoTests extends
|
||||
*/
|
||||
public void testCreateJobWithExistingName() {
|
||||
|
||||
jobDao.createJobInstance("ScheduledJob", jobParameters);
|
||||
jobInstanceDao.createJobInstance("ScheduledJob", jobParameters);
|
||||
|
||||
// Modifying the key should bring back a completely different
|
||||
// JobInstance
|
||||
@@ -138,12 +144,12 @@ public abstract class AbstractJobDaoTests extends
|
||||
.toJobParameters();
|
||||
|
||||
List jobs;
|
||||
jobs = jobDao.findJobInstances("ScheduledJob", jobParameters);
|
||||
jobs = jobInstanceDao.findJobInstances("ScheduledJob", jobParameters);
|
||||
assertEquals(1, jobs.size());
|
||||
JobInstance jobInstance = (JobInstance) jobs.get(0);
|
||||
assertEquals(jobParameters, jobInstance.getJobParameters());
|
||||
|
||||
jobs = jobDao.findJobInstances("ScheduledJob", tempProps);
|
||||
jobs = jobInstanceDao.findJobInstances("ScheduledJob", tempProps);
|
||||
assertEquals(0, jobs.size());
|
||||
|
||||
}
|
||||
@@ -151,12 +157,12 @@ public abstract class AbstractJobDaoTests extends
|
||||
public void testUpdateJob() {
|
||||
// Update the returned job with a new status
|
||||
JobExecution newExecution = new JobExecution(jobInstance);
|
||||
jobDao.saveJobExecution(newExecution);
|
||||
jobExecutionDao.saveJobExecution(newExecution);
|
||||
jobInstance.setLastExecution(newExecution);
|
||||
jobDao.updateJobInstance(jobInstance);
|
||||
jobInstanceDao.updateJobInstance(jobInstance);
|
||||
|
||||
// The job just updated should be found, with the saved status.
|
||||
List jobs = jobDao.findJobInstances(job.getName(), jobParameters);
|
||||
List jobs = jobInstanceDao.findJobInstances(job.getName(), jobParameters);
|
||||
assertTrue(jobs.size() == 1);
|
||||
JobInstance tempJob = (JobInstance) jobs.get(0);
|
||||
assertTrue(jobInstance.equals(tempJob));
|
||||
@@ -165,13 +171,13 @@ public abstract class AbstractJobDaoTests extends
|
||||
|
||||
public void testGetJobExecution(){
|
||||
|
||||
JobExecution tempExecution = jobDao.getJobExecution(jobExecution.getId());
|
||||
JobExecution tempExecution = jobExecutionDao.getJobExecution(jobExecution.getId());
|
||||
assertEquals(jobExecution, tempExecution);
|
||||
}
|
||||
|
||||
public void testJobInstanceLastExecution(){
|
||||
//ensure the last execution id is being stored
|
||||
JobExecution lastJobExecution = jobDao.getJobExecution(jobInstance.getLastExecution().getId());
|
||||
JobExecution lastJobExecution = jobExecutionDao.getJobExecution(jobInstance.getLastExecution().getId());
|
||||
assertEquals(lastJobExecution, jobExecution);
|
||||
}
|
||||
|
||||
@@ -180,7 +186,7 @@ public abstract class AbstractJobDaoTests extends
|
||||
|
||||
try {
|
||||
JobInstance testJob = new JobInstance(null, null);
|
||||
jobDao.updateJobInstance(testJob);
|
||||
jobInstanceDao.updateJobInstance(testJob);
|
||||
fail();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
@@ -191,7 +197,7 @@ public abstract class AbstractJobDaoTests extends
|
||||
|
||||
JobInstance testJob = null;
|
||||
try {
|
||||
jobDao.updateJobInstance(testJob);
|
||||
jobInstanceDao.updateJobInstance(testJob);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
}
|
||||
@@ -202,9 +208,9 @@ public abstract class AbstractJobDaoTests extends
|
||||
jobExecution.setStatus(BatchStatus.COMPLETED);
|
||||
jobExecution.setExitStatus(ExitStatus.FINISHED);
|
||||
jobExecution.setEndTime(new Date(System.currentTimeMillis()));
|
||||
jobDao.updateJobExecution(jobExecution);
|
||||
jobExecutionDao.updateJobExecution(jobExecution);
|
||||
|
||||
List executions = jobDao.findJobExecutions(jobInstance);
|
||||
List executions = jobExecutionDao.findJobExecutions(jobInstance);
|
||||
assertEquals(executions.size(), 1);
|
||||
validateJobExecution(jobExecution, (JobExecution) executions.get(0));
|
||||
|
||||
@@ -212,7 +218,7 @@ public abstract class AbstractJobDaoTests extends
|
||||
|
||||
public void testSaveJobExecution(){
|
||||
|
||||
List executions = jobDao.findJobExecutions(jobInstance);
|
||||
List executions = jobExecutionDao.findJobExecutions(jobInstance);
|
||||
assertEquals(executions.size(), 1);
|
||||
validateJobExecution(jobExecution, (JobExecution) executions.get(0));
|
||||
}
|
||||
@@ -222,7 +228,7 @@ public abstract class AbstractJobDaoTests extends
|
||||
// id is invalid
|
||||
JobExecution execution = new JobExecution(jobInstance, new Long(29432));
|
||||
try {
|
||||
jobDao.updateJobExecution(execution);
|
||||
jobExecutionDao.updateJobExecution(execution);
|
||||
fail("Expected NoSuchBatchDomainObjectException");
|
||||
} catch (NoSuchBatchDomainObjectException ex) {
|
||||
// expected
|
||||
@@ -233,7 +239,7 @@ public abstract class AbstractJobDaoTests extends
|
||||
|
||||
JobExecution execution = new JobExecution(jobInstance);
|
||||
try {
|
||||
jobDao.updateJobExecution(execution);
|
||||
jobExecutionDao.updateJobExecution(execution);
|
||||
fail();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// expected
|
||||
@@ -243,26 +249,26 @@ public abstract class AbstractJobDaoTests extends
|
||||
public void testIncrementExecutionCount() {
|
||||
|
||||
// 1 JobExection already added in setup
|
||||
assertEquals(jobDao.getJobExecutionCount(jobInstance.getId()), 1);
|
||||
assertEquals(jobExecutionDao.getJobExecutionCount(jobInstance.getId()), 1);
|
||||
|
||||
// Save new JobExecution for same job
|
||||
JobExecution testJobExecution = new JobExecution(jobInstance);
|
||||
jobDao.saveJobExecution(testJobExecution);
|
||||
jobExecutionDao.saveJobExecution(testJobExecution);
|
||||
// JobExecutionCount should be incremented by 1
|
||||
assertEquals(jobDao.getJobExecutionCount(jobInstance.getId()), 2);
|
||||
assertEquals(jobExecutionDao.getJobExecutionCount(jobInstance.getId()), 2);
|
||||
}
|
||||
|
||||
public void testZeroExecutionCount() {
|
||||
|
||||
JobInstance testJob = jobDao.createJobInstance("test", new JobParameters());
|
||||
JobInstance testJob = jobInstanceDao.createJobInstance("test", new JobParameters());
|
||||
// no jobExecutions saved for new job, count should be 0
|
||||
assertEquals(jobDao.getJobExecutionCount(testJob.getId()), 0);
|
||||
assertEquals(jobExecutionDao.getJobExecutionCount(testJob.getId()), 0);
|
||||
}
|
||||
|
||||
public void testJobWithSimpleJobIdentifier() throws Exception {
|
||||
|
||||
// Create job.
|
||||
jobInstance = jobDao.createJobInstance("test", jobParameters);
|
||||
jobInstance = jobInstanceDao.createJobInstance("test", jobParameters);
|
||||
|
||||
List jobs = jdbcTemplate.queryForList(
|
||||
"SELECT * FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", new Object[] { jobInstance
|
||||
@@ -274,9 +280,9 @@ public abstract class AbstractJobDaoTests extends
|
||||
|
||||
public void testJobWithDefaultJobIdentifier() throws Exception {
|
||||
// Create job.
|
||||
jobInstance = jobDao.createJobInstance("testDefault", jobParameters);
|
||||
jobInstance = jobInstanceDao.createJobInstance("testDefault", jobParameters);
|
||||
|
||||
List jobs = jobDao.findJobInstances("testDefault", jobParameters);
|
||||
List jobs = jobInstanceDao.findJobInstances("testDefault", jobParameters);
|
||||
|
||||
assertEquals(1, jobs.size());
|
||||
assertEquals(jobParameters.getString("job.key"), ((JobInstance) jobs.get(0))
|
||||
@@ -286,7 +292,7 @@ public abstract class AbstractJobDaoTests extends
|
||||
|
||||
public void testFindJobExecutions(){
|
||||
|
||||
List results = jobDao.findJobExecutions(jobInstance);
|
||||
List results = jobExecutionDao.findJobExecutions(jobInstance);
|
||||
assertEquals(results.size(), 1);
|
||||
validateJobExecution(jobExecution, (JobExecution)results.get(0));
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSourceSpringContextTests {
|
||||
|
||||
protected JobDao jobDao;
|
||||
protected JobInstanceDao jobInstanceDao;
|
||||
|
||||
protected StepInstanceDao stepInstanceDao;
|
||||
|
||||
@@ -64,8 +64,8 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour
|
||||
|
||||
protected ExecutionAttributes executionAttributes;
|
||||
|
||||
public void setJobDao(JobDao jobDao) {
|
||||
this.jobDao = jobDao;
|
||||
public void setJobInstanceDao(JobInstanceDao jobInstanceDao) {
|
||||
this.jobInstanceDao = jobInstanceDao;
|
||||
}
|
||||
|
||||
public void setStepInstanceDao(StepInstanceDao stepInstanceDao) {
|
||||
@@ -90,7 +90,7 @@ public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSour
|
||||
*/
|
||||
protected void onSetUpInTransaction() throws Exception {
|
||||
Job job = new JobSupport("TestJob");
|
||||
jobInstance = jobDao.createJobInstance(job.getName(), jobParameters);
|
||||
jobInstance = jobInstanceDao.createJobInstance(job.getName(), jobParameters);
|
||||
step1 = stepInstanceDao.createStepInstance(jobInstance, "TestStep1");
|
||||
step2 = stepInstanceDao.createStepInstance(jobInstance, "TestStep2");
|
||||
jobExecution = new JobExecution(step2.getJobInstance());
|
||||
|
||||
@@ -31,8 +31,8 @@ import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer
|
||||
*
|
||||
*/
|
||||
public class JdbcJobDaoQueryTests extends TestCase {
|
||||
|
||||
JdbcJobDao sqlDao;
|
||||
|
||||
JdbcJobExecutionDao jobExecutionDao;
|
||||
|
||||
List list = new ArrayList();
|
||||
|
||||
@@ -41,8 +41,9 @@ public class JdbcJobDaoQueryTests extends TestCase {
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
sqlDao = new JdbcJobDao();
|
||||
sqlDao.setJobExecutionIncrementer(new DataFieldMaxValueIncrementer() {
|
||||
|
||||
jobExecutionDao = new JdbcJobExecutionDao();
|
||||
jobExecutionDao.setJobExecutionIncrementer(new DataFieldMaxValueIncrementer() {
|
||||
|
||||
public int nextIntValue() throws DataAccessException {
|
||||
return 0;
|
||||
@@ -60,14 +61,14 @@ public class JdbcJobDaoQueryTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testTablePrefix() throws Exception {
|
||||
sqlDao.setTablePrefix("FOO_");
|
||||
sqlDao.setJdbcTemplate(new JdbcTemplate() {
|
||||
jobExecutionDao.setTablePrefix("FOO_");
|
||||
jobExecutionDao.setJdbcTemplate(new JdbcTemplate() {
|
||||
public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException {
|
||||
list.add(sql);
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
sqlDao.saveJobExecution(new JobInstance(new Long(11), new JobParameters()).createJobExecution());
|
||||
jobExecutionDao.saveJobExecution(new JobInstance(new Long(11), new JobParameters()).createJobExecution());
|
||||
assertEquals(1, list.size());
|
||||
String query = (String) list.get(0);
|
||||
assertTrue("Query did not contain FOO_:" + query, query.indexOf("FOO_") >= 0);
|
||||
|
||||
@@ -10,7 +10,8 @@ public class JdbcJobDaoTests extends AbstractJobDaoTests {
|
||||
public static final String LONG_STRING = "A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String ";
|
||||
|
||||
protected void onSetUpBeforeTransaction() throws Exception {
|
||||
((JdbcJobDao) jobDao).setTablePrefix(JdbcJobDao.DEFAULT_TABLE_PREFIX);
|
||||
((JdbcJobInstanceDao) jobInstanceDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
((JdbcJobExecutionDao) jobExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
}
|
||||
|
||||
public void testUpdateJobExecutionWithLongExitCode() {
|
||||
@@ -18,7 +19,7 @@ public class JdbcJobDaoTests extends AbstractJobDaoTests {
|
||||
assertTrue(LONG_STRING.length() > 250);
|
||||
jobExecution.setExitStatus(ExitStatus.FINISHED
|
||||
.addExitDescription(LONG_STRING));
|
||||
jobDao.updateJobExecution(jobExecution);
|
||||
jobExecutionDao.updateJobExecution(jobExecution);
|
||||
|
||||
List executions = jdbcTemplate.queryForList(
|
||||
"SELECT * FROM BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=?",
|
||||
|
||||
@@ -46,7 +46,7 @@ public class JdbcStepDaoPrefixTests extends TestCase {
|
||||
|
||||
stepInstanceDao = new JdbcStepInstanceDao();
|
||||
stepExecutionDao = new JdbcStepExecutionDao();
|
||||
stepExecutionDao.setJobDao(new MapJobDao());
|
||||
stepExecutionDao.setJobExecutionDao(new MapJobDao());
|
||||
stepExecutionIncrementer = (DataFieldMaxValueIncrementer)stepExecutionIncrementerControl.getMock();
|
||||
stepIncrementer = (DataFieldMaxValueIncrementer)stepIncrementerControl.getMock();
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ public class JdbcStepDaoTests extends AbstractStepDaoTests {
|
||||
private static final String LONG_STRING = JdbcJobDaoTests.LONG_STRING;
|
||||
|
||||
protected void onSetUpBeforeTransaction() throws Exception {
|
||||
((JdbcStepInstanceDao) stepInstanceDao).setTablePrefix(JdbcJobDao.DEFAULT_TABLE_PREFIX);
|
||||
((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix(JdbcJobDao.DEFAULT_TABLE_PREFIX);
|
||||
((JdbcStepInstanceDao) stepInstanceDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX);
|
||||
}
|
||||
|
||||
public void testTablePrefix() throws Exception {
|
||||
|
||||
@@ -202,7 +202,7 @@ public class SimpleStepExecutorTests extends TestCase {
|
||||
|
||||
public void testRepository() throws Exception {
|
||||
|
||||
SimpleJobRepository repository = new SimpleJobRepository(new MapJobDao(), new MapStepDao(), new MapStepDao());
|
||||
SimpleJobRepository repository = new SimpleJobRepository(new MapJobDao(), new MapJobDao(), new MapStepDao(), new MapStepDao());
|
||||
stepExecutor.setRepository(repository);
|
||||
|
||||
StepInstance step = new StepInstance(new Long(1));
|
||||
|
||||
@@ -55,7 +55,7 @@ public class StepExecutorInterruptionTests extends TestCase {
|
||||
|
||||
public void setUp() throws Exception {
|
||||
|
||||
jobRepository = new SimpleJobRepository(jobDao, stepDao, stepDao);
|
||||
jobRepository = new SimpleJobRepository(jobDao, jobDao, stepDao, stepDao);
|
||||
|
||||
JobSupport jobConfiguration = new JobSupport();
|
||||
step = new RepeatOperationsStep();
|
||||
|
||||
@@ -5,10 +5,15 @@
|
||||
|
||||
<import resource="data-source-context.xml" />
|
||||
|
||||
<bean id="jobDao" class="org.springframework.batch.execution.repository.dao.JdbcJobDao" >
|
||||
<bean id="jobInstanceDao" class="org.springframework.batch.execution.repository.dao.JdbcJobInstanceDao" >
|
||||
<property name="jdbcTemplate" ref="jdbcTemplate" />
|
||||
<property name="jobIncrementer" ref="jobIncrementer" />
|
||||
<property name="jobExecutionIncrementer" ref="jobExecutionIncrementer" />
|
||||
<property name="jobIncrementer" ref="jobIncrementer" />
|
||||
<property name="jobExecutionDao" ref="jobExecutionDao" />
|
||||
</bean>
|
||||
|
||||
<bean id="jobExecutionDao" class="org.springframework.batch.execution.repository.dao.JdbcJobExecutionDao" >
|
||||
<property name="jdbcTemplate" ref="jdbcTemplate" />
|
||||
<property name="jobExecutionIncrementer" ref="jobExecutionIncrementer" />
|
||||
</bean>
|
||||
|
||||
<bean id="stepInstanceDao" class="org.springframework.batch.execution.repository.dao.JdbcStepInstanceDao" >
|
||||
@@ -20,7 +25,7 @@
|
||||
<bean id="stepExecutionDao" class="org.springframework.batch.execution.repository.dao.JdbcStepExecutionDao" >
|
||||
<property name="jdbcTemplate" ref="jdbcTemplate" />
|
||||
<property name="stepExecutionIncrementer" ref="stepExecutionIncrementer" />
|
||||
<property name="jobDao" ref="jobDao"/>
|
||||
<property name="jobExecutionDao" ref="jobExecutionDao"/>
|
||||
</bean>
|
||||
|
||||
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
<bean id="simpleJobRepository"
|
||||
class="org.springframework.batch.execution.repository.SimpleJobRepository">
|
||||
<constructor-arg ref="jobDao" />
|
||||
<constructor-arg ref="jobDao" />
|
||||
<constructor-arg ref="stepDao" />
|
||||
<constructor-arg ref="stepDao" />
|
||||
|
||||
Reference in New Issue
Block a user