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 c94a12741..207d3c92d 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 @@ -31,7 +31,7 @@ import org.springframework.batch.item.ExecutionContext; * * @author Dave Syer * @author Michael Minella - * + * @author Will Schipp * @since 2.0 */ public interface JobExplorer { @@ -108,6 +108,17 @@ public interface JobExplorer { * @return the set of job names that have been executed */ List getJobNames(); + + /** + * Fetch {@link JobInstance} values in descending order of creation (and + * there for usually of first execution) with a 'like'/wildcard criteria. + * + * @param jobName + * @param start + * @param count + * @return + */ + List getJobInstancesByJobName(String jobName, int start, int count); /** * Query the repository for the number of unique {@link JobInstance}s 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 82479888b..eeef93f79 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 @@ -35,6 +35,7 @@ import org.springframework.batch.core.repository.dao.StepExecutionDao; * @author Dave Syer * @author Lucas Ward * @author Michael Minella + * @author Will Schipp * * @see JobExplorer * @see JobInstanceDao @@ -195,7 +196,6 @@ public class SimpleJobExplorer implements JobExplorer { * requires JobParameters) plus StepExecutions */ private void getJobExecutionDependencies(JobExecution jobExecution) { - JobInstance jobInstance = jobInstanceDao.getJobInstance(jobExecution); stepExecutionDao.addStepExecutions(jobExecution); jobExecution.setJobInstance(jobInstance); @@ -208,4 +208,9 @@ public class SimpleJobExplorer implements JobExplorer { stepExecution.setExecutionContext(ecDao.getExecutionContext(stepExecution)); } } + + @Override + public List getJobInstancesByJobName(String jobName, int start, int count) { + return jobInstanceDao.findJobInstancesByName(jobName, start, count); + } } 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 e8f2f2d36..8bb1c6fab 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 @@ -50,10 +50,15 @@ import org.springframework.util.StringUtils; * @author Dave Syer * @author Robert Kasanicky * @author Michael Minella + * @author Will Schipp */ public class JdbcJobInstanceDao extends AbstractJdbcBatchMetadataDao implements JobInstanceDao, InitializingBean { + private static final String STAR_WILDCARD = "*"; + + private static final String SQL_WILDCARD = "%"; + private static final String CREATE_JOB_INSTANCE = "INSERT into %PREFIX%JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION)" + " values (?, ?, ?, ?)"; @@ -74,6 +79,8 @@ JobInstanceDao, InitializingBean { private static final String FIND_JOB_NAMES = "SELECT distinct JOB_NAME from %PREFIX%JOB_INSTANCE order by JOB_NAME"; private static final String FIND_LAST_JOBS_BY_NAME = "SELECT JOB_INSTANCE_ID, JOB_NAME from %PREFIX%JOB_INSTANCE where JOB_NAME = ? order by JOB_INSTANCE_ID desc"; + + private static final String FIND_LAST_JOBS_LIKE_NAME = "SELECT JOB_INSTANCE_ID, JOB_NAME from %PREFIX%JOB_INSTANCE where JOB_NAME like ? order by JOB_INSTANCE_ID desc"; private DataFieldMaxValueIncrementer jobIncrementer; @@ -296,4 +303,42 @@ JobInstanceDao, InitializingBean { return jobInstance; } } + + @Override + public List findJobInstancesByName(String jobName,final int start, + final int count) { + @SuppressWarnings("rawtypes") + ResultSetExtractor extractor = new ResultSetExtractor() { + + private List list = new ArrayList(); + + @Override + public Object extractData(ResultSet rs) throws SQLException, + DataAccessException { + int rowNum = 0; + while (rowNum < start && rs.next()) { + rowNum++; + } + while (rowNum < start + count && rs.next()) { + ParameterizedRowMapper rowMapper = new JobInstanceRowMapper(); + list.add(rowMapper.mapRow(rs, rowNum)); + rowNum++; + } + return list; + } + + }; + + //check if the name contains a wildcard + if (jobName.contains(STAR_WILDCARD)) { + //swap for sql wildcard + jobName = jobName.replaceAll("\\" + STAR_WILDCARD, SQL_WILDCARD); + }//end if + + @SuppressWarnings("unchecked") + List result = (List) getJdbcTemplate().query(getQuery(FIND_LAST_JOBS_LIKE_NAME), + new Object[] { jobName }, extractor); + + return result; + } } 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 f5cb89dcf..f72548021 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 @@ -79,6 +79,9 @@ public interface JobInstanceDao { * Fetch the last job instances with the provided name, sorted backwards by * primary key. * + * if using the JdbcJobInstance, you can provide the jobName with a wildcard + * (e.g. *Job) to return 'like' job names. (e.g. *Job will return 'someJob' + * and 'otherJob') * * @param jobName the job name * @param start the start index of the instances to return @@ -93,6 +96,17 @@ public interface JobInstanceDao { * @return the names of all job instances */ List getJobNames(); + + /** + * Fetch the last job instances with the provided name, sorted backwards by + * primary key, using a 'like' criteria + * + * @param jobName + * @param start + * @param count + * @return + */ + List findJobInstancesByName(String jobName, int start, int count); /** 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 2da7b7443..1a89a5337 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 @@ -132,4 +132,9 @@ public class MapJobInstanceDao implements JobInstanceDao { return count; } } + + @Override + public List findJobInstancesByName(String jobName, int start, int count) { + return getJobInstances(jobName,start,count); + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java index b50c45f7e..2061575dd 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java @@ -486,6 +486,11 @@ public class CommandLineJobRunnerTests { throw new UnsupportedOperationException(); } + @Override + public List getJobInstancesByJobName(String jobName, int start, int count) { + throw new UnsupportedOperationException(); + } + @Override public int getJobInstanceCount(String jobName) throws NoSuchJobException { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java index dcbe80f54..0f0f61299 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java @@ -16,9 +16,11 @@ package org.springframework.batch.core.repository.dao; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.math.BigInteger; import java.security.MessageDigest; +import java.util.List; import javax.sql.DataSource; @@ -86,4 +88,22 @@ public class JdbcJobInstanceDaoTests extends AbstractJobInstanceDaoTests { assertEquals("Wrong hash: " + value, 32, value.length()); assertEquals(value, output.toString()); } + + @Test + public void testJobInstanceWildcard() { + //look up a job using a wildcard (* substituted to %) + // unrelated job instance that should be ignored by the query + dao.createJobInstance("anotherJob", new JobParameters()); + // we need two instances of the same job to check ordering + dao.createJobInstance("someJob", new JobParameters()); + //now look for them + List jobInstances = dao.findJobInstancesByName("*Job", 0, 2); + assertEquals(2, jobInstances.size()); + for (JobInstance instance : jobInstances) { + assertTrue(instance.getJobName().contains("Job")); + }//end for + //try with after wildcards + jobInstances = dao.getJobInstances("Job*", 0, 2); + assertTrue(jobInstances.isEmpty()); + } }