From 3f340e2cf0b4064367f7a0fdbd82ffee991194e5 Mon Sep 17 00:00:00 2001 From: dsyer Date: Tue, 13 Nov 2007 19:03:56 +0000 Subject: [PATCH] OPEN - issue BATCH-194: Incorrect exception handling when using Hibernate http://opensource.atlassian.com/projects/spring/browse/BATCH-194 --- .../sample/dao/HibernateCreditWriter.java | 34 +++++++-- .../src/main/resources/CustomerCredit.hbm.xml | 18 +++-- .../src/main/resources/jobs/hibernateJob.xml | 76 +++++++++---------- .../sample/AbstractBatchLauncherTests.java | 52 ++++++++----- .../AbstractCustomerCreditIncreaseTests.java | 3 +- .../AbstractValidatingBatchLauncherTests.java | 3 +- .../GracefulShutdownFunctionalTest.java | 2 +- .../HibernateFailureJobFunctionalTests.java | 66 ++++++++++++++++ 8 files changed, 178 insertions(+), 76 deletions(-) create mode 100644 samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java diff --git a/samples/src/main/java/org/springframework/batch/sample/dao/HibernateCreditWriter.java b/samples/src/main/java/org/springframework/batch/sample/dao/HibernateCreditWriter.java index e64aa0341..54411842e 100644 --- a/samples/src/main/java/org/springframework/batch/sample/dao/HibernateCreditWriter.java +++ b/samples/src/main/java/org/springframework/batch/sample/dao/HibernateCreditWriter.java @@ -20,23 +20,47 @@ import org.springframework.orm.hibernate3.support.HibernateDaoSupport; /** * @author Lucas Ward - * + * */ public class HibernateCreditWriter extends HibernateDaoSupport implements CustomerCreditWriter { - /* (non-Javadoc) + private boolean failOnFlush = false; + + /* + * (non-Javadoc) + * * @see org.springframework.batch.sample.dao.CustomerCreditWriter#write(org.springframework.batch.sample.domain.CustomerCredit) */ public void write(CustomerCredit customerCredit) { - getHibernateTemplate().update(customerCredit); + if (!failOnFlush ) { + getHibernateTemplate().update(customerCredit); + } else { + // try to insert one with a duplicate ID + CustomerCredit newCredit = new CustomerCredit(); + newCredit.setId(customerCredit.getId()); + newCredit.setName(customerCredit.getName()); + newCredit.setCredit(customerCredit.getCredit()); + getHibernateTemplate().save(newCredit); + } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.io.OutputSource#write(java.lang.Object) */ public void write(Object output) { - write((CustomerCredit)output); + write((CustomerCredit) output); + } + + /** + * Public setter for the {@link boolean} property. + * + * @param failOnFlush true if you want to fail on flush (for testing) + */ + public void setFailOnFlush(boolean failOnFlush) { + this.failOnFlush = failOnFlush; } } diff --git a/samples/src/main/resources/CustomerCredit.hbm.xml b/samples/src/main/resources/CustomerCredit.hbm.xml index 02d231884..ed57d20eb 100644 --- a/samples/src/main/resources/CustomerCredit.hbm.xml +++ b/samples/src/main/resources/CustomerCredit.hbm.xml @@ -4,13 +4,15 @@ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/samples/src/main/resources/jobs/hibernateJob.xml b/samples/src/main/resources/jobs/hibernateJob.xml index 6975e84e7..49ed25aeb 100644 --- a/samples/src/main/resources/jobs/hibernateJob.xml +++ b/samples/src/main/resources/jobs/hibernateJob.xml @@ -1,18 +1,18 @@ - - - Example for Hibernate integration. - + Example for Hibernate integration. - - + + @@ -21,19 +21,16 @@ - - + + - - - - - - - + + @@ -42,33 +39,34 @@ - + + + + + - - - - - CustomerCredit.hbm.xml - - - - - hibernate.dialect=org.hibernate.dialect.HSQLDialect - - - + + + + + CustomerCredit.hbm.xml + + + + + hibernate.dialect=org.hibernate.dialect.HSQLDialect + + + - - - - - - - + \ No newline at end of file diff --git a/samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java b/samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java index 13219427f..812c7fdaa 100644 --- a/samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java +++ b/samples/src/test/java/org/springframework/batch/sample/AbstractBatchLauncherTests.java @@ -24,46 +24,60 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.AbstractDependencyInjectionSpringContextTests; /** - * Abstract unit test for running functional tests by getting context locations for - * both the container and configuration separately and having them auto wired in - * by type. This allows the two to be completely separated, and remove any - * 'configuration coupling' between the two. However, it is still purely - * theoretical until a decision is made as to how job configuration and container - * configuration files are pulled together. + * Abstract unit test for running functional tests by getting context locations + * for both the container and configuration separately and having them auto + * wired in by type. This allows the two to be completely separated, and remove + * any 'configuration coupling' between the two. However, it is still purely + * theoretical until a decision is made as to how job configuration and + * container configuration files are pulled together. * * @author Lucas Ward - * + * */ -public abstract class AbstractBatchLauncherTests extends AbstractDependencyInjectionSpringContextTests { +public abstract class AbstractBatchLauncherTests extends + AbstractDependencyInjectionSpringContextTests { private static final String CONTAINER_DEFINITION_LOCATION = "simple-container-definition.xml"; - + JobLauncher launcher; - JobConfiguration jobConfiguration; - - /* (non-Javadoc) + private JobConfiguration jobConfiguration; + + /* + * (non-Javadoc) + * * @see org.springframework.test.AbstractSingleSpringContextTests#createApplicationContext(java.lang.String[]) */ protected ConfigurableApplicationContext createApplicationContext( String[] locations) { - ApplicationContext parent = new ClassPathXmlApplicationContext(CONTAINER_DEFINITION_LOCATION); + ApplicationContext parent = new ClassPathXmlApplicationContext( + CONTAINER_DEFINITION_LOCATION); return new ClassPathXmlApplicationContext(locations, parent); } - - public void setLauncher(JobLauncher bootstrap){ + + public void setLauncher(JobLauncher bootstrap) { this.launcher = bootstrap; } - + /** * Public setter for the {@link JobConfiguration} property. - * - * @param jobConfiguration the jobConfiguration to set + * + * @param jobConfiguration + * the jobConfiguration to set */ public void setJobConfiguration(JobConfiguration jobConfiguration) { this.jobConfiguration = jobConfiguration; } - + protected String getJobName() { return jobConfiguration.getName(); } + + /** + * @throws Exception + * + */ + public void testLaunchJob() throws Exception { + launcher.run(getJobName()); + launcher.stop(); + } } diff --git a/samples/src/test/java/org/springframework/batch/sample/AbstractCustomerCreditIncreaseTests.java b/samples/src/test/java/org/springframework/batch/sample/AbstractCustomerCreditIncreaseTests.java index d7b3646e1..ac5308754 100644 --- a/samples/src/test/java/org/springframework/batch/sample/AbstractCustomerCreditIncreaseTests.java +++ b/samples/src/test/java/org/springframework/batch/sample/AbstractCustomerCreditIncreaseTests.java @@ -24,8 +24,7 @@ public abstract class AbstractCustomerCreditIncreaseTests extends AbstractValida private static final String CREDIT_COLUMN = "CREDIT"; private List creditsBeforeUpdate; - - + public void setJdbcTemplate(JdbcOperations jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } diff --git a/samples/src/test/java/org/springframework/batch/sample/AbstractValidatingBatchLauncherTests.java b/samples/src/test/java/org/springframework/batch/sample/AbstractValidatingBatchLauncherTests.java index 02395567b..6b79c1e12 100644 --- a/samples/src/test/java/org/springframework/batch/sample/AbstractValidatingBatchLauncherTests.java +++ b/samples/src/test/java/org/springframework/batch/sample/AbstractValidatingBatchLauncherTests.java @@ -31,8 +31,7 @@ public abstract class AbstractValidatingBatchLauncherTests extends AbstractBatch public void testLaunchJob() throws Exception { validatePreConditions(); - launcher.run(getJobName()); - launcher.stop(); + super.testLaunchJob(); validatePostConditions(); } diff --git a/samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTest.java b/samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTest.java index 82f885cc2..cbd7500b7 100644 --- a/samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTest.java +++ b/samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTest.java @@ -34,7 +34,7 @@ public class GracefulShutdownFunctionalTest extends AbstractBatchLauncherTests { return new String[] {"jobs/infiniteLoopJob.xml"}; } - public void testJob()throws Exception { + public void testLaunchJob() throws Exception { final List errors = new ArrayList(); Thread jobThread = new Thread(){ diff --git a/samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java b/samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java new file mode 100644 index 000000000..0cdcfd560 --- /dev/null +++ b/samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java @@ -0,0 +1,66 @@ +package org.springframework.batch.sample; + +import org.springframework.batch.sample.dao.HibernateCreditWriter; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.orm.hibernate3.HibernateJdbcException; + +/** + * Test for HibernateJob - checks that customer credit has been updated to + * expected value. + * + * @author Dave Syer + */ +public class HibernateFailureJobFunctionalTests extends + AbstractBatchLauncherTests { + + private HibernateCreditWriter writer; + private JdbcOperations jdbcTemplate; + + public void setJdbcTemplate(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + /** + * Public setter for the {@link HibernateCreditWriter} property. + * + * @param writer + * the writer to set + */ + public void setWriter(HibernateCreditWriter writer) { + this.writer = writer; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.test.AbstractSingleSpringContextTests#onTearDown() + */ + protected void onTearDown() throws Exception { + super.onTearDown(); + writer.setFailOnFlush(false); + } + + protected String[] getConfigLocations() { + return new String[] { "jobs/hibernateJob.xml" }; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.sample.AbstractValidatingBatchLauncherTests#testLaunchJob() + */ + public void testLaunchJob() throws Exception { + writer.setFailOnFlush(true); + + int before = jdbcTemplate.queryForInt("SELECT COUNT(*) from CUSTOMER"); + assertTrue(before>0); + try { + super.testLaunchJob(); + } catch (HibernateJdbcException e) { + // Comment this out to see the test fail... + // fail("This exception is evil"); + } + int after = jdbcTemplate.queryForInt("SELECT COUNT(*) from CUSTOMER"); + assertEquals(before, after); + } +}