diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptor.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptor.java
new file mode 100644
index 000000000..5d9d1aadb
--- /dev/null
+++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptor.java
@@ -0,0 +1,90 @@
+package org.springframework.batch.execution.repository.dao;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.hibernate.EmptyInterceptor;
+import org.springframework.batch.core.domain.JobInstance;
+import org.springframework.batch.core.runtime.JobIdentifier;
+import org.springframework.batch.execution.runtime.ScheduledJobIdentifier;
+import org.springframework.util.ClassUtils;
+
+/**
+ * Hibernate interceptor that can distinguish between the various
+ * {@link JobIdentifier} strategies in a {@link JobInstance}. Its task is to
+ * return the correct entity name based on the type of {@link JobIdentifier}
+ * used. There is necessarily some tight coupling between this and the Hibernate
+ * mappings for {@link JobInstance} because the map from {@link JobIdentifier}
+ * type to entity name is in both places.
+ *
+ *
+ * @author Dave Syer
+ *
+ */
+public class EntityNameInterceptor extends EmptyInterceptor {
+
+ private static final String SIMPLE_JOB_INSTANCE = "SimpleJobInstance";
+ private Map identifierTypes = new HashMap();
+
+ {
+ identifierTypes.put(ScheduledJobIdentifier.class,
+ "ScheduledJobInstance");
+ };
+
+ /**
+ * Public setter for the identifier types. A map from Class (the
+ * {@link JobIdentifier} implementation) to String (the entity name). If a
+ * map from String to String is provided it will be interpreted as a map
+ * from class name to entity name.
+ *
+ * @throws IllegalArgumentException
+ * if a String key is provided that is not a Class name.
+ *
+ * @param types
+ * the identifierTypes to set
+ */
+ public void setIdentifierTypes(Map types) {
+ this.identifierTypes = new HashMap();
+ for (Iterator iterator = types.entrySet().iterator(); iterator
+ .hasNext();) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ Object key = entry.getKey();
+ if (key instanceof Class) {
+ identifierTypes.put(key, entry.getValue());
+ } else {
+ try {
+ Class classKey = ClassUtils.forName(key.toString());
+ identifierTypes.put(classKey, entry.getValue());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(
+ "Could not convert key in identifierTypes to type Class: ["
+ + key + "]", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * If the object is a {@link JobInstance} search the identifier types for an
+ * entity name based on the {@link JobIdentifier} type. Fall back to
+ * SimpleJobIdentifier if the value is not found.
+ *
+ * @see org.hibernate.EmptyInterceptor#getEntityName(java.lang.Object)
+ */
+ public String getEntityName(Object object) {
+ if (object instanceof JobInstance) {
+ JobInstance instance = (JobInstance) object;
+ for (Iterator iterator = identifierTypes.entrySet().iterator(); iterator
+ .hasNext();) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ Class key = (Class) entry.getKey();
+ if (key.isAssignableFrom(instance.getIdentifier().getClass())) {
+ return (String) entry.getValue();
+ }
+ }
+ return SIMPLE_JOB_INSTANCE;
+ }
+ return super.getEntityName(object);
+ }
+}
diff --git a/execution/src/main/java/org/springframework/batch/execution/repository/dao/HibernateJobDao.java b/execution/src/main/java/org/springframework/batch/execution/repository/dao/HibernateJobDao.java
index f77c12577..2192f9172 100644
--- a/execution/src/main/java/org/springframework/batch/execution/repository/dao/HibernateJobDao.java
+++ b/execution/src/main/java/org/springframework/batch/execution/repository/dao/HibernateJobDao.java
@@ -49,9 +49,7 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
*/
public JobInstance createJob(JobIdentifier jobIdentifier) {
- ScheduledJobIdentifier jobRuntimeInformation = (ScheduledJobIdentifier) jobIdentifier;
-
- validateJobIdentifier(jobRuntimeInformation);
+ validateJobIdentifier(jobIdentifier);
JobInstance job = new JobInstance();
job.setIdentifier(jobIdentifier);
@@ -75,13 +73,16 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
validateJobIdentifier(jobRuntimeInformation);
- List list = this.getHibernateTemplate().executeFind(new HibernateCallback() {
- public Object doInHibernate(Session session) {
- Criteria criteria = session.createCriteria(JobInstance.class);
- criteria.add(Expression.eq("identifier", jobRuntimeInformation));
- return criteria.list();
- }
- });
+ List list = this.getHibernateTemplate().executeFind(
+ new HibernateCallback() {
+ public Object doInHibernate(Session session) {
+ Criteria criteria = session
+ .createCriteria(JobInstance.class);
+ criteria.add(Expression.eq("identifier",
+ jobRuntimeInformation));
+ return criteria.list();
+ }
+ });
return list;
}
@@ -93,12 +94,16 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
Assert.notNull(jobId, "JobId cannot be null");
- Long result = (Long) this.getHibernateTemplate().execute(new HibernateCallback() {
- public Object doInHibernate(Session session) {
- return session.createQuery("select count(id) from JobExecution where jobId = :jobId").setLong("jobId",
- jobId.longValue()).uniqueResult();
- }
- });
+ Long result = (Long) this.getHibernateTemplate().execute(
+ new HibernateCallback() {
+ public Object doInHibernate(Session session) {
+ return session
+ .createQuery(
+ "select count(id) from JobExecution where jobId = :jobId")
+ .setLong("jobId", jobId.longValue())
+ .uniqueResult();
+ }
+ });
return (result == null) ? 0 : result.intValue();
}
@@ -137,13 +142,16 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
validateJobExecution(jobExecution);
if (jobExecution.getId() == null) {
- throw new IllegalArgumentException("JobExecution ID cannot be null. JobExecution must be saved "
- + "before it can be updated.");
+ throw new IllegalArgumentException(
+ "JobExecution ID cannot be null. JobExecution must be saved "
+ + "before it can be updated.");
}
- if (getHibernateTemplate().get(JobExecution.class, jobExecution.getId()) == null) {
- throw new NoSuchBatchDomainObjectException("Invalid JobExecution, ID " + jobExecution.getId()
- + " not found.");
+ if (getHibernateTemplate()
+ .get(JobExecution.class, jobExecution.getId()) == null) {
+ throw new NoSuchBatchDomainObjectException(
+ "Invalid JobExecution, ID " + jobExecution.getId()
+ + " not found.");
}
getHibernateTemplate().update(jobExecution);
@@ -156,13 +164,15 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
final Long jobId = job.getId();
- List list = this.getHibernateTemplate().executeFind(new HibernateCallback() {
- public Object doInHibernate(Session session) {
- Criteria criteria = session.createCriteria(JobExecution.class);
- criteria.add(Expression.eq("jobId", jobId));
- return criteria.list();
- }
- });
+ List list = this.getHibernateTemplate().executeFind(
+ new HibernateCallback() {
+ public Object doInHibernate(Session session) {
+ Criteria criteria = session
+ .createCriteria(JobExecution.class);
+ criteria.add(Expression.eq("jobId", jobId));
+ return criteria.list();
+ }
+ });
return list;
}
@@ -176,9 +186,12 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
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.");
+ 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.");
}
/*
@@ -186,11 +199,19 @@ public class HibernateJobDao extends HibernateDaoSupport implements JobDao {
* acceptable for any field to be blank, however null fields may cause odd
* and vague exception reports from the database driver.
*/
- private void validateJobIdentifier(ScheduledJobIdentifier jobRuntimeInformation) {
+ private void validateJobIdentifier(JobIdentifier jobIdentifier) {
- Assert.notNull(jobRuntimeInformation, "JobRuntimeInformation cannot be null.");
- Assert.notNull(jobRuntimeInformation.getName(), "JobRuntimeInformation name cannot be null.");
- Assert.notNull(jobRuntimeInformation.getJobStream(), "JobRuntimeInformation JobStream cannot be null.");
- Assert.notNull(jobRuntimeInformation.getScheduleDate(), "JobRuntimeInformation ScheduleDate cannot be null.");
+ Assert.notNull(jobIdentifier, "JobRuntimeInformation cannot be null.");
+ Assert.notNull(jobIdentifier.getName(),
+ "JobRuntimeInformation name cannot be null.");
+
+ if (jobIdentifier instanceof ScheduledJobIdentifier) {
+ ScheduledJobIdentifier jobRuntimeInformation = (ScheduledJobIdentifier) jobIdentifier;
+
+ Assert.notNull(jobRuntimeInformation.getJobStream(),
+ "JobRuntimeInformation JobStream cannot be null.");
+ Assert.notNull(jobRuntimeInformation.getScheduleDate(),
+ "JobRuntimeInformation ScheduleDate cannot be null.");
+ }
}
}
diff --git a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobInstance.hbm.xml b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobInstance.hbm.xml
index 81c3bdd12..874944459 100644
--- a/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobInstance.hbm.xml
+++ b/execution/src/main/resources/org/springframework/batch/execution/repository/dao/JobInstance.hbm.xml
@@ -1,4 +1,4 @@
-
+
+
&job-generator;
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptorTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptorTests.java
new file mode 100644
index 000000000..97e1f7261
--- /dev/null
+++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/EntityNameInterceptorTests.java
@@ -0,0 +1,49 @@
+package org.springframework.batch.execution.repository.dao;
+
+import java.util.Collections;
+
+import org.springframework.batch.core.domain.JobInstance;
+import org.springframework.batch.core.runtime.SimpleJobIdentifier;
+import org.springframework.batch.execution.runtime.ScheduledJobIdentifier;
+
+import junit.framework.TestCase;
+
+public class EntityNameInterceptorTests extends TestCase {
+
+ private EntityNameInterceptor interceptor = new EntityNameInterceptor();
+
+ public void testGetEntityNameForScheduledJobIdentifier() {
+ JobInstance job = new JobInstance();
+ job.setIdentifier(new ScheduledJobIdentifier("foo"));
+ assertEquals("ScheduledJobInstance", interceptor.getEntityName(job));
+ }
+
+ public void testGetEntityNameForSimpleJobIdentifier() {
+ JobInstance job = new JobInstance();
+ job.setIdentifier(new SimpleJobIdentifier("foo"));
+ assertEquals("SimpleJobInstance", interceptor.getEntityName(job));
+ }
+
+ public void testSetIdentifierTypesWithString() {
+ interceptor.setIdentifierTypes(Collections.singletonMap(ScheduledJobIdentifier.class.getName(), "foo"));
+ JobInstance job = new JobInstance();
+ job.setIdentifier(new ScheduledJobIdentifier("foo"));
+ assertEquals("foo", interceptor.getEntityName(job));
+ }
+
+ public void testSetIdentifierTypesWithClass() {
+ interceptor.setIdentifierTypes(Collections.singletonMap(ScheduledJobIdentifier.class, "foo"));
+ JobInstance job = new JobInstance();
+ job.setIdentifier(new ScheduledJobIdentifier("foo"));
+ assertEquals("foo", interceptor.getEntityName(job));
+ }
+
+ public void testSetIdentifierTypesWithInvalidClassName() {
+ try {
+ interceptor.setIdentifierTypes(Collections.singletonMap("FooBarNotAClass", "foo"));
+ fail("Expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateJobDaoTests.java b/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateJobDaoTests.java
index a8e29ae63..b43ec6b63 100644
--- a/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateJobDaoTests.java
+++ b/execution/src/test/java/org/springframework/batch/execution/repository/dao/HibernateJobDaoTests.java
@@ -22,6 +22,7 @@ import java.util.Map;
import org.hibernate.SessionFactory;
import org.springframework.batch.core.domain.BatchStatus;
+import org.springframework.batch.core.runtime.SimpleJobIdentifier;
import org.springframework.util.ClassUtils;
public class HibernateJobDaoTests extends SqlJobDaoTests {
@@ -49,4 +50,18 @@ public class HibernateJobDaoTests extends SqlJobDaoTests {
assertEquals(jobExecution.getEndTime(), ((Map)executions.get(0)).get("END_TIME"));
}
+ public void testJobWithSimpleJobIdentifier() throws Exception {
+ SimpleJobIdentifier jobIdentifier = new SimpleJobIdentifier("Job1");
+
+ // Create job.
+ job = jobDao.createJob(jobIdentifier);
+
+ sessionFactory.getCurrentSession().flush();
+
+ List jobs = jdbcTemplate.queryForList("SELECT * FROM BATCH_JOB where ID=?", new Object[] {job.getId()});
+ assertEquals(1, jobs.size());
+ assertEquals(job.getName(), ((Map)jobs.get(0)).get("JOB_NAME"));
+
+ }
+
}
diff --git a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-context.xml b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-context.xml
index cabd910c8..cda532b01 100644
--- a/execution/src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-context.xml
+++ b/execution/src/test/resources/org/springframework/batch/execution/repository/dao/hibernate-context.xml
@@ -24,6 +24,9 @@
+
+
+