diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobDao.java index 372c1c5fd..f93432baa 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobDao.java @@ -20,7 +20,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; -import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -33,13 +32,10 @@ import org.springframework.batch.core.domain.JobExecution; import org.springframework.batch.core.domain.JobIdentifier; import org.springframework.batch.core.domain.JobInstance; import org.springframework.batch.core.domain.JobInstanceProperties; -import org.springframework.batch.core.domain.JobInstancePropertiesBuilder; import org.springframework.batch.core.repository.NoSuchBatchDomainObjectException; import org.springframework.batch.repeat.ExitStatus; import org.springframework.beans.factory.InitializingBean; -import org.springframework.dao.DataRetrievalFailureException; import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; import org.springframework.util.Assert; @@ -142,7 +138,7 @@ public class JdbcJobDao implements JobDao, InitializingBean { private String createJobKey(JobInstanceProperties jobInstanceProperties){ Map props = jobInstanceProperties.getParameters(); - StringBuilder stringBuilder = new StringBuilder(); + StringBuilder stringBuilder = new StringBuilder("params:"); for(Iterator it = props.entrySet().iterator();it.hasNext();){ Entry entry = (Entry)it.next(); stringBuilder.append(entry.toString() + ";"); @@ -492,49 +488,7 @@ public class JdbcJobDao implements JobDao, InitializingBean { } } - - /* - * Private inner class for mapping values from the JOB_PARAMETERS table into the java - * JobParameters class. TODO: is this going to be used? If not can we delete it? - */ - private static class JobParameterCallbackHandler implements RowCallbackHandler{ - - private JobInstancePropertiesBuilder parametersBuilder; - public JobParameterCallbackHandler() { - parametersBuilder = new JobInstancePropertiesBuilder(); - } - - public void processRow(ResultSet rs) throws SQLException { - - ParameterType parameterType = ParameterType.getType(rs.getString("TYPE_CD")); - - String key = rs.getString("KEY"); - - if(parameterType == ParameterType.STRING){ - parametersBuilder.addString(key, rs.getString("STRING_VAL")); - } - else if(parameterType == ParameterType.LONG){ - parametersBuilder.addLong(key, new Long(rs.getLong("LONG_VAL"))); - } - else if(parameterType == ParameterType.DATE){ - //I debated about just passing the Timestamp in, however, I didn't want there to be any equality - //issues when comparing a java.util.Date to a timestamp. - Timestamp ts = rs.getTimestamp("DATE_VAL"); - parametersBuilder.addDate(key, new Date(ts.getTime())); - } - else{ - //invalid type code, error out. - throw new DataRetrievalFailureException("Invalid JobParameter type"); - } - } - - public JobInstanceProperties getJobParmeters(){ - return parametersBuilder.toJobParameters(); - } - - } - private static class ParameterType { private final String type; diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifier.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifier.java index 18d0b880a..aeee9aeef 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifier.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/runtime/ScheduledJobIdentifier.java @@ -21,33 +21,57 @@ import java.util.Date; import org.springframework.batch.core.domain.JobIdentifier; import org.springframework.batch.core.domain.JobInstancePropertiesBuilder; +/** + * Convenient {@link JobIdentifier} implementation that identifies itself by a + * {@link Date} as well as an optional String key. The time portion of the + * schedule date is significant, and clients are responsible for truncating it + * if it represents a date rather than a timestamp. + * + * @author Dave Syer + * + */ public class ScheduledJobIdentifier extends DefaultJobIdentifier implements JobIdentifier { - + public static final String SCHEDULE_DATE = "schedule.date"; - + ScheduledJobIdentifier() { this(null); } - + public ScheduledJobIdentifier(String name) { super(name); } /** - * @param name - * @param key + * Convenience constructor that leaves the schedule date null. + * + * @param name the name of the job + * @param key a unique key for this execution */ public ScheduledJobIdentifier(String name, String key) { super(name, key); } - - public ScheduledJobIdentifier(String name, Date scheduleDate){ + + /** + * Convenience constructor that leaves the key null. + * + * @param name the name of the job + * @param scheduleDate a timestamp + */ + public ScheduledJobIdentifier(String name, Date scheduleDate) { super(name, new JobInstancePropertiesBuilder().addDate(SCHEDULE_DATE, scheduleDate).toJobParameters()); } - - public ScheduledJobIdentifier(String name, String jobKey, Date scheduleDate){ - super(name, new JobInstancePropertiesBuilder().addString(ScheduledJobIdentifier.JOB_KEY, jobKey). - addDate(SCHEDULE_DATE, scheduleDate).toJobParameters()); + + /** + * Convenience constructor with all properties. + * + * @param name the name of the job + * @param key a unique key for this execution + * @param scheduleDate a timestamp + */ + public ScheduledJobIdentifier(String name, String key, Date scheduleDate) { + super(name, new JobInstancePropertiesBuilder().addString(ScheduledJobIdentifier.JOB_KEY, key).addDate( + SCHEDULE_DATE, scheduleDate).toJobParameters()); } public Date getScheduleDate() { diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java index f43cf600e..33a2762ad 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractJobDaoTests.java @@ -272,6 +272,39 @@ public abstract class AbstractJobDaoTests extends } + public void testJobWithScheduledJobIdentifier() throws Exception { + Date date = new Date(); + ScheduledJobIdentifier jobIdentifier = new ScheduledJobIdentifier("Job1", "testKey", date); + + // Create job. + job = jobDao.createJob(jobIdentifier); + + List jobs = jobDao.findJobs(jobIdentifier); + + assertEquals(1, jobs.size()); + assertEquals(job.getName(), ((JobInstance) jobs.get(0)).getName()); + assertEquals(jobIdentifier.getJobKey(), ((JobInstance) jobs.get(0)). + getIdentifier().getJobInstanceProperties().getString(DefaultJobIdentifier.JOB_KEY)); + + } + + public void testJobWithScheduledJobIdentifierAndDifferentTime() throws Exception { + Date date = new Date(); + ScheduledJobIdentifier jobIdentifier = new ScheduledJobIdentifier("Job1", "testKey", date); + + // Create job. + job = jobDao.createJob(jobIdentifier); + + Date later = new Date(date.getTime()+3600000); + ScheduledJobIdentifier laterIdentifier = new ScheduledJobIdentifier("Job1", "testKey", later); + + List jobs = jobDao.findJobs(laterIdentifier); + + // Different timestamp is different identifier... + assertEquals(0, jobs.size()); + + } + public void testFindJobExecutions(){ List results = jobDao.findJobExecutions(job); diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoTests.java index d11f4d5b5..bc176728b 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoTests.java @@ -3,6 +3,7 @@ package org.springframework.batch.execution.repository.dao; import java.util.List; import java.util.Map; +import org.springframework.batch.core.runtime.SimpleJobIdentifier; import org.springframework.batch.repeat.ExitStatus; public class JdbcJobDaoTests extends AbstractJobDaoTests { @@ -16,16 +17,21 @@ public class JdbcJobDaoTests extends AbstractJobDaoTests { public void testUpdateJobExecutionWithLongExitCode() { assertTrue(LONG_STRING.length() > 250); - jobExecution.setExitStatus(ExitStatus.FINISHED - .addExitDescription(LONG_STRING)); + jobExecution.setExitStatus(ExitStatus.FINISHED.addExitDescription(LONG_STRING)); jobDao.update(jobExecution); - List executions = jdbcTemplate.queryForList( - "SELECT * FROM BATCH_JOB_EXECUTION where JOB_ID=?", + List executions = jdbcTemplate.queryForList("SELECT * FROM BATCH_JOB_EXECUTION where JOB_ID=?", new Object[] { job.getId() }); assertEquals(1, executions.size()); - assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)) - .get("EXIT_MESSAGE")); + assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)).get("EXIT_MESSAGE")); + } + + public void testJobInstanceParametersNotNullOrEmptyWithSimpleJobIdentifier() { + job = jobDao.createJob(new SimpleJobIdentifier("foo")); + Map map = jdbcTemplate.queryForMap("SELECT * FROM BATCH_JOB_INSTANCE where ID=?", + new Object[] { job.getId() }); + String key = (String) map.get("JOB_KEY"); + assertTrue("Key should be non-zero length (otherwise Oracle will treat as null)", key.length()>0); } }