diff --git a/archetypes/simple-cli-javaconfig/pom.xml b/archetypes/simple-cli-javaconfig/pom.xml index 3dc32e258..6b625a80c 100644 --- a/archetypes/simple-cli-javaconfig/pom.xml +++ b/archetypes/simple-cli-javaconfig/pom.xml @@ -14,7 +14,7 @@ The ./bin/runJob.(sh|bat) script from the extracted deployment archive can be invoked to run the job. - 3.2.0.RELEASE + 3.2.7.RELEASE 3.0.0.BUILD-SNAPSHOT false 4.10 diff --git a/archetypes/simple-cli/pom.xml b/archetypes/simple-cli/pom.xml index 91edf6896..606c7fd08 100644 --- a/archetypes/simple-cli/pom.xml +++ b/archetypes/simple-cli/pom.xml @@ -14,7 +14,7 @@ The ./bin/runJob.(sh|bat) script from the extracted deployment archive can be invoked to run the job. - 3.2.0.RELEASE + 3.2.7.RELEASE 3.0.0.BUILD-SNAPSHOT false 4.10 diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/PooledEmbeddedDataSource.java b/spring-batch-core/src/test/java/org/springframework/batch/core/PooledEmbeddedDataSource.java new file mode 100644 index 000000000..51ccae603 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/PooledEmbeddedDataSource.java @@ -0,0 +1,120 @@ +/* + * Copyright 2014 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.core; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.logging.Logger; + +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; + +/** + * As of Spring 3.2, when a context is closed, the shutdown method is + * called on any beans that are registered. With an embedded database + * that uses a connection pool, this can leave the connection pool open + * with stale connections. This wraps an {@link EmbeddedDatabase} and + * ignores calls to {@link EmbeddedDatabase#shutdown()}. + * + * @author Phil Webb + * @since 3.0 + */ +public class PooledEmbeddedDataSource implements EmbeddedDatabase { + + private final EmbeddedDatabase dataSource; + + /** + * @param dataSource The database to be wrapped + */ + public PooledEmbeddedDataSource(EmbeddedDatabase dataSource) { + this.dataSource = dataSource; + } + + /* (non-Javadoc) + * @see javax.sql.DataSource#getConnection() + */ + @Override + public Connection getConnection() throws SQLException { + return this.dataSource.getConnection(); + } + + /* (non-Javadoc) + * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) + */ + @Override + public Connection getConnection(String username, String password) throws SQLException { + return this.dataSource.getConnection(username, password); + } + + /* (non-Javadoc) + * @see javax.sql.CommonDataSource#getLogWriter() + */ + @Override + public PrintWriter getLogWriter() throws SQLException { + return this.dataSource.getLogWriter(); + } + + /* (non-Javadoc) + * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter) + */ + @Override + public void setLogWriter(PrintWriter out) throws SQLException { + this.dataSource.setLogWriter(out); + } + + /* (non-Javadoc) + * @see javax.sql.CommonDataSource#getLoginTimeout() + */ + @Override + public int getLoginTimeout() throws SQLException { + return this.dataSource.getLoginTimeout(); + } + + /* (non-Javadoc) + * @see javax.sql.CommonDataSource#setLoginTimeout(int) + */ + @Override + public void setLoginTimeout(int seconds) throws SQLException { + this.dataSource.setLoginTimeout(seconds); + } + + /* (non-Javadoc) + * @see java.sql.Wrapper#unwrap(java.lang.Class) + */ + @Override + public T unwrap(Class iface) throws SQLException { + return this.dataSource.unwrap(iface); + } + + /* (non-Javadoc) + * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) + */ + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return this.dataSource.isWrapperFor(iface); + } + + public Logger getParentLogger() { + return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + } + + /* (non-Javadoc) + * @see org.springframework.jdbc.datasource.embedded.EmbeddedDatabase#shutdown() + */ + @Override + public void shutdown() { + } +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/SpringBeanJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/SpringBeanJobTests.java index 5f9e242bb..0699307de 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/SpringBeanJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/SpringBeanJobTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007 the original author or authors. + * Copyright 2006-2014 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. @@ -16,8 +16,10 @@ package org.springframework.batch.core; -import junit.framework.TestCase; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import org.junit.Test; import org.springframework.batch.core.job.JobSupport; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.support.ChildBeanDefinition; @@ -25,34 +27,42 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.StaticApplicationContext; -public class SpringBeanJobTests extends TestCase { +public class SpringBeanJobTests { + @Test public void testBeanName() throws Exception { StaticApplicationContext context = new StaticApplicationContext(); JobSupport configuration = new JobSupport(); context.getAutowireCapableBeanFactory().initializeBean(configuration, "bean"); + context.refresh(); assertNotNull(configuration.getName()); configuration.setBeanName("foo"); context.getAutowireCapableBeanFactory().initializeBean(configuration, "bean"); assertEquals("bean", configuration.getName()); + context.close(); } + @Test public void testBeanNameWithBeanDefinition() throws Exception { GenericApplicationContext context = new GenericApplicationContext(); ConstructorArgumentValues args = new ConstructorArgumentValues(); args.addGenericArgumentValue("foo"); context.registerBeanDefinition("bean", new RootBeanDefinition( JobSupport.class, args, null)); + + context.refresh(); JobSupport configuration = (JobSupport) context .getBean("bean"); assertNotNull(configuration.getName()); assertEquals("foo", configuration.getName()); configuration.setBeanName("bar"); assertEquals("foo", configuration.getName()); + context.close(); } + @Test public void testBeanNameWithParentBeanDefinition() throws Exception { GenericApplicationContext context = new GenericApplicationContext(); ConstructorArgumentValues args = new ConstructorArgumentValues(); @@ -60,6 +70,7 @@ public class SpringBeanJobTests extends TestCase { context.registerBeanDefinition("parent", new RootBeanDefinition( JobSupport.class, args, null)); context.registerBeanDefinition("bean", new ChildBeanDefinition("parent")); + context.refresh(); JobSupport configuration = (JobSupport) context .getBean("bean"); assertNotNull(configuration.getName()); @@ -68,5 +79,6 @@ public class SpringBeanJobTests extends TestCase { assertEquals("bar", configuration.getName()); configuration.setName("foo"); assertEquals("foo", configuration.getName()); + context.close(); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java index 76aa3d805..cb55c5607 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2014 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. @@ -18,6 +18,7 @@ package org.springframework.batch.core.configuration.annotation; import javax.annotation.PostConstruct; import javax.sql.DataSource; +import org.springframework.batch.core.PooledEmbeddedDataSource; import org.springframework.batch.core.Step; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -31,13 +32,13 @@ import org.springframework.util.ClassUtils; @Configuration public class DataSourceConfiguration { - + @Autowired private Environment environment; - + @Autowired private ResourceLoader resourceLoader; - + @PostConstruct protected void initialize() { ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); @@ -45,10 +46,10 @@ public class DataSourceConfiguration { populator.setContinueOnError(true); DatabasePopulatorUtils.execute(populator, dataSource()); } - + @Bean public DataSource dataSource() { - return new EmbeddedDatabaseFactory().getDatabase(); + return new PooledEmbeddedDataSource(new EmbeddedDatabaseFactory().getDatabase()); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java index 993d1345d..8e5a1bb53 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java @@ -42,7 +42,7 @@ import org.springframework.context.annotation.Configuration; /** * @author Dave Syer - * + * */ public class JobBuilderConfigurationTests { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JsrJobParametersConverterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JsrJobParametersConverterTests.java index 5c809ad5a..80598be36 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JsrJobParametersConverterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/JsrJobParametersConverterTests.java @@ -15,6 +15,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.PooledEmbeddedDataSource; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; public class JsrJobParametersConverterTests { @@ -24,10 +25,10 @@ public class JsrJobParametersConverterTests { @BeforeClass public static void setupDatabase() { - dataSource = new EmbeddedDatabaseBuilder(). + dataSource = new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder(). addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql"). addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql"). - build(); + build()); } @Before diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/BatchParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/BatchParserTests.java index 8afc4694a..01eacfe45 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/BatchParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/BatchParserTests.java @@ -23,6 +23,7 @@ import javax.sql.DataSource; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import org.springframework.batch.core.PooledEmbeddedDataSource; import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.xml.DummyItemProcessor; @@ -101,10 +102,10 @@ public class BatchParserTests { @Bean DataSource dataSource() { - return new EmbeddedDatabaseBuilder(). + return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder(). addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql"). addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql"). - build(); + build()); } } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java index 52d61eac4..96a019eae 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java @@ -10,22 +10,22 @@ public class JdbcExecutionContextDaoTests extends AbstractExecutionContextDaoTes @Override protected JobInstanceDao getJobInstanceDao() { - return (JobInstanceDao) applicationContext.getBean("jobInstanceDao", JobInstanceDao.class); + return applicationContext.getBean("jobInstanceDao", JobInstanceDao.class); } @Override protected JobExecutionDao getJobExecutionDao() { - return (JobExecutionDao) applicationContext.getBean("jobExecutionDao", JdbcJobExecutionDao.class); + return applicationContext.getBean("jobExecutionDao", JdbcJobExecutionDao.class); } @Override protected StepExecutionDao getStepExecutionDao() { - return (StepExecutionDao) applicationContext.getBean("stepExecutionDao", StepExecutionDao.class); + return applicationContext.getBean("stepExecutionDao", StepExecutionDao.class); } @Override protected ExecutionContextDao getExecutionContextDao() { - return (ExecutionContextDao) applicationContext.getBean("executionContextDao", JdbcExecutionContextDao.class); + return applicationContext.getBean("executionContextDao", JdbcExecutionContextDao.class); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoTests.java index 1ad220481..81bca09ab 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoTests.java @@ -1,16 +1,17 @@ package org.springframework.batch.core.repository.dao; -import static org.junit.Assert.*; -import org.junit.runner.RunWith; -import org.junit.Before; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.List; import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; import org.springframework.batch.core.ExitStatus; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/XStreamExecutionContextStringSerializerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/XStreamExecutionContextStringSerializerTests.java index ba5071499..834b2624c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/XStreamExecutionContextStringSerializerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/XStreamExecutionContextStringSerializerTests.java @@ -9,6 +9,7 @@ import java.math.BigDecimal; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import org.junit.Before; import org.junit.Test; @@ -30,6 +31,15 @@ public class XStreamExecutionContextStringSerializerTests { serializer = serializerDeserializer; } + @Test + public void testSerializePropertiesArrayContainer() throws Exception { + PropertiesArrayContainer container = new PropertiesArrayContainer(); + container.setProps(new Properties[3]); + + PropertiesArrayContainer result = (PropertiesArrayContainer) serializationRoundTrip(container); + assertEquals(3, result.getProps().length); + } + @Test public void testSerializeAMap() throws Exception { Map m1 = new HashMap(); @@ -39,7 +49,7 @@ public class XStreamExecutionContextStringSerializerTests { m1.put("object3", new Date(123456790123L)); m1.put("object4", new Double(1234567.1234D)); - Map m2 = serializationRoundTrip(m1); + Map m2 = (Map) serializationRoundTrip(m1); compareContexts(m1, m2); } @@ -61,7 +71,7 @@ public class XStreamExecutionContextStringSerializerTests { o1.setObj(o2); m1.put("co", o1); - Map m2 = serializationRoundTrip(m1); + Map m2 = (Map) serializationRoundTrip(m1); compareContexts(m1, m2); } @@ -80,14 +90,14 @@ public class XStreamExecutionContextStringSerializerTests { } @SuppressWarnings("unchecked") - private Map serializationRoundTrip(Map m1) throws IOException { + private Object serializationRoundTrip(Object m1) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); serializer.serialize(m1, out); String s = out.toString(); ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes()); - Map m2 = (Map) serializer.deserialize(in); + Object m2 = serializer.deserialize(in); return m2; } @@ -133,15 +143,27 @@ public class XStreamExecutionContextStringSerializerTests { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } ComplexObject that = (ComplexObject) o; - if (map != null ? !map.equals(that.map) : that.map != null) return false; - if (name != null ? !name.equals(that.name) : that.name != null) return false; - if (number != null ? !number.equals(that.number) : that.number != null) return false; - if (obj != null ? !obj.equals(that.obj) : that.obj != null) return false; + if (map != null ? !map.equals(that.map) : that.map != null) { + return false; + } + if (name != null ? !name.equals(that.name) : that.name != null) { + return false; + } + if (number != null ? !number.equals(that.number) : that.number != null) { + return false; + } + if (obj != null ? !obj.equals(that.obj) : that.obj != null) { + return false; + } return true; } @@ -160,6 +182,17 @@ public class XStreamExecutionContextStringSerializerTests { public String toString() { return "ComplexObject [name=" + name + ", number=" + number + "]"; } + } + public static class PropertiesArrayContainer { + private Properties[] props; + + public Properties[] getProps() { + return props; + } + + public void setProps(Properties[] props) { + this.props = props; + } } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java index 284a05eeb..42d67efff 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java @@ -25,7 +25,7 @@ import org.springframework.transaction.annotation.Transactional; /** * Repository tests using JDBC DAOs (rather than mocks). - * + * * @author Robert Kasanicky */ @RunWith(SpringJUnit4ClassRunner.class) @@ -186,4 +186,4 @@ public class SimpleJobRepositoryIntegrationTests { assertEquals(jobExecution, jobRepository.getLastJobExecution(job.getName(), jobParameters)); } -} \ No newline at end of file +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java index b2ffe0c1c..7f4b454cb 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java @@ -15,6 +15,7 @@ import org.springframework.batch.core.ItemWriteListener; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.PooledEmbeddedDataSource; import org.springframework.batch.core.SkipListener; import org.springframework.batch.core.Step; import org.springframework.batch.core.StepExecution; @@ -184,11 +185,11 @@ public class RegisterMultiListenerTests { @Bean public DataSource dataSource(){ - return new EmbeddedDatabaseBuilder() + return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder() .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql") .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql") .setType(EmbeddedDatabaseType.HSQL) - .build(); + .build()); } @Override @@ -214,11 +215,11 @@ public class RegisterMultiListenerTests { @Bean public DataSource dataSource(){ - return new EmbeddedDatabaseBuilder() + return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder() .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql") .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql") .setType(EmbeddedDatabaseType.HSQL) - .build(); + .build()); } @Override diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java index 8db0ffd12..df49d65cc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java @@ -53,7 +53,7 @@ import org.springframework.transaction.support.TransactionTemplate; /** * @author Dave Syer - * + * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "/org/springframework/batch/core/repository/dao/sql-dao-test.xml") @@ -138,12 +138,12 @@ public class AsyncChunkOrientedStepIntegrationTests { assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); // Need a transaction so one connection is enough to get job execution and its parameters StepExecution lastStepExecution = new TransactionTemplate(transactionManager) - .execute(new TransactionCallback() { - @Override - public StepExecution doInTransaction(TransactionStatus status) { - return jobRepository.getLastStepExecution(jobExecution.getJobInstance(), step.getName()); - } - }); + .execute(new TransactionCallback() { + @Override + public StepExecution doInTransaction(TransactionStatus status) { + return jobRepository.getLastStepExecution(jobExecution.getJobInstance(), step.getName()); + } + }); assertEquals(lastStepExecution, stepExecution); assertFalse(lastStepExecution == stepExecution); } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml index 02785c96d..09f0119fd 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> @@ -37,4 +37,4 @@ - \ No newline at end of file + diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/sql-dao-test.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/sql-dao-test.xml index af59d264d..72147766f 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/sql-dao-test.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/sql-dao-test.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> @@ -36,4 +36,4 @@ - \ No newline at end of file + diff --git a/spring-batch-infrastructure-tests/pom.xml b/spring-batch-infrastructure-tests/pom.xml index e49977afc..17233922c 100644 --- a/spring-batch-infrastructure-tests/pom.xml +++ b/spring-batch-infrastructure-tests/pom.xml @@ -140,7 +140,7 @@ 2.8.1 test - + com.thoughtworks.xstream xstream test diff --git a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderAsyncTests.java b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderAsyncTests.java index 646daaf2d..cd5396539 100644 --- a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderAsyncTests.java +++ b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderAsyncTests.java @@ -22,15 +22,15 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.batch.item.sample.Foo; -import org.springframework.test.jdbc.JdbcTestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.orm.ibatis.SqlMapClientFactoryBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.jdbc.JdbcTestUtils; import com.ibatis.sqlmap.client.SqlMapClient; +import com.ibatis.sqlmap.client.SqlMapClientBuilder; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "JdbcPagingItemReaderCommonTests-context.xml") @@ -55,7 +55,7 @@ public class IbatisPagingItemReaderAsyncTests { @Before public void init() { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); maxId = jdbcTemplate.queryForInt("SELECT MAX(ID) from T_FOOS"); for (int i = ITEM_COUNT; i > maxId; i--) { jdbcTemplate.update("INSERT into T_FOOS (ID,NAME,VALUE) values (?, ?, ?)", i, "foo" + i, i); @@ -65,7 +65,7 @@ public class IbatisPagingItemReaderAsyncTests { @After public void destroy() { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.update("DELETE from T_FOOS where ID>?", maxId); } @@ -99,6 +99,7 @@ public class IbatisPagingItemReaderAsyncTests { .newFixedThreadPool(THREAD_COUNT)); for (int i = 0; i < THREAD_COUNT; i++) { completionService.submit(new Callable>() { + @Override public List call() throws Exception { List list = new ArrayList(); Foo next = null; @@ -130,17 +131,13 @@ public class IbatisPagingItemReaderAsyncTests { } private IbatisPagingItemReader getItemReader() throws Exception { - SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); - factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); - factory.setDataSource(dataSource); - factory.afterPropertiesSet(); - SqlMapClient sqlMapClient = createSqlMapClient(); + SqlMapClient sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(new ClassPathResource("ibatis-config.xml", getClass()).getInputStream()); IbatisPagingItemReader reader = new IbatisPagingItemReader(); if ("postgres".equals(System.getProperty("ENVIRONMENT"))) { - reader.setQueryId("getPagedFoosPostgres"); + reader.setQueryId("getPagedFoosPostgres"); } else if ("oracle".equals(System.getProperty("ENVIRONMENT"))) { - reader.setQueryId("getPagedFoosOracle"); + reader.setQueryId("getPagedFoosOracle"); } else { reader.setQueryId("getPagedFoos"); } @@ -154,11 +151,7 @@ public class IbatisPagingItemReaderAsyncTests { } private SqlMapClient createSqlMapClient() throws Exception { - SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); - factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); - factory.setDataSource(dataSource); - factory.afterPropertiesSet(); - return (SqlMapClient) factory.getObject(); + return SqlMapClientBuilder.buildSqlMapClient(new ClassPathResource("ibatis-config.xml", getClass()).getInputStream()); } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/IbatisBatchItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/IbatisBatchItemWriter.java index 6b57aa098..1afeac70b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/IbatisBatchItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/IbatisBatchItemWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2013 the original author or authors. + * Copyright 2006-2014 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. @@ -15,27 +15,34 @@ */ package org.springframework.batch.item.database; +import java.sql.Connection; import java.sql.SQLException; import java.util.List; +import javax.sql.DataSource; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.item.ItemWriter; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.orm.ibatis.SqlMapClientCallback; -import org.springframework.orm.ibatis.SqlMapClientTemplate; +import org.springframework.jdbc.CannotGetJdbcConnectionException; +import org.springframework.jdbc.datasource.DataSourceUtils; +import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; +import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator; +import org.springframework.jdbc.support.SQLExceptionTranslator; +import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator; import org.springframework.util.Assert; import com.ibatis.sqlmap.client.SqlMapClient; -import com.ibatis.sqlmap.client.SqlMapExecutor; +import com.ibatis.sqlmap.client.SqlMapSession; import com.ibatis.sqlmap.engine.execution.BatchException; import com.ibatis.sqlmap.engine.execution.BatchResult; /** * {@link ItemWriter} that uses the batching features from - * SqlMapClientTemplate to execute a batch of statements for all items + * SqlMapClient to execute a batch of statements for all items * provided.
* * The user must provide an iBATIS statement id that points to the SQL statement defined @@ -44,21 +51,35 @@ import com.ibatis.sqlmap.engine.execution.BatchResult; * It is expected that {@link #write(List)} is called inside a transaction.
* * The writer is thread safe after its properties are set (normal singleton - * behavior), so it can be used to write in multiple concurrent transactions. + * behavior), so it can be used to write in multiple concurrent transactions.
+ * + * Note: This reader was refactored as part of Spring Batch 3.0 to use the iBatis + * APIs directly instead of using Spring's SqlMapClientTemplate as part of the upgrade to + * support Spring 4. * * @author Thomas Risberg + * @author Michael Minella * @since 2.0 + * @deprecated as of Spring Batch 3.0, in favor of the native Spring Batch support + * in the MyBatis follow-up project (http://mybatis.github.io/spring/) */ +@Deprecated public class IbatisBatchItemWriter implements ItemWriter, InitializingBean { protected static final Log logger = LogFactory.getLog(IbatisBatchItemWriter.class); - private SqlMapClientTemplate sqlMapClientTemplate; - private String statementId; private boolean assertUpdates = true; + private SqlMapClient sqlMapClient; + + private DataSource dataSource; + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + /** * Public setter for the flag that determines whether an assertion is made * that all items cause at least one row to be updated. @@ -75,18 +96,7 @@ public class IbatisBatchItemWriter implements ItemWriter, InitializingBean * @param sqlMapClient the SqlMapClient */ public void setSqlMapClient(SqlMapClient sqlMapClient) { - if (sqlMapClientTemplate == null) { - this.sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient); - } - } - - /** - * Public setter for the SqlMapClientTemplate. - * - * @param sqlMapClientTemplate the SqlMapClientTemplate - */ - public void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate) { - this.sqlMapClientTemplate = sqlMapClientTemplate; + this.sqlMapClient = sqlMapClient; } /** @@ -104,7 +114,7 @@ public class IbatisBatchItemWriter implements ItemWriter, InitializingBean */ @Override public void afterPropertiesSet() { - Assert.notNull(sqlMapClientTemplate, "A SqlMapClient or a SqlMapClientTemplate is required."); + Assert.notNull(sqlMapClient, "A SqlMapClient is required."); Assert.notNull(statementId, "A statementId is required."); } @@ -120,23 +130,7 @@ public class IbatisBatchItemWriter implements ItemWriter, InitializingBean logger.debug("Executing batch with " + items.size() + " items."); } - @SuppressWarnings("unchecked") - List results = (List) sqlMapClientTemplate.execute( - new SqlMapClientCallback() { - @Override - public Object doInSqlMapClient(SqlMapExecutor executor) - throws SQLException { - executor.startBatch(); - for (T item : items) { - executor.update(statementId, item); - } - try { - return executor.executeBatchDetailed(); - } catch (BatchException e) { - throw e.getBatchUpdateException(); - } - } - }); + List results = execute(items); if (assertUpdates) { if (results.size() != 1) { @@ -154,9 +148,81 @@ public class IbatisBatchItemWriter implements ItemWriter, InitializingBean } } } - } - } + @SuppressWarnings("unchecked") + private List execute(final List items) { + // We always need to use a SqlMapSession, as we need to pass a Spring-managed + // Connection (potentially transactional) in. This shouldn't be necessary if + // we run against a TransactionAwareDataSourceProxy underneath, but unfortunately + // we still need it to make iBATIS batch execution work properly: If iBATIS + // doesn't recognize an existing transaction, it automatically executes the + // batch for every single statement... + + SqlMapSession session = this.sqlMapClient.openSession(); + if (logger.isDebugEnabled()) { + logger.debug("Opened SqlMapSession [" + session + "] for iBATIS operation"); + } + Connection ibatisCon = null; + + try { + Connection springCon = null; + boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy); + + // Obtain JDBC Connection to operate on... + try { + ibatisCon = session.getCurrentConnection(); + if (ibatisCon == null) { + springCon = (transactionAware ? + dataSource.getConnection() : DataSourceUtils.doGetConnection(dataSource)); + session.setUserConnection(springCon); + if (logger.isDebugEnabled()) { + logger.debug("Obtained JDBC Connection [" + springCon + "] for iBATIS operation"); + } + } + else { + if (logger.isDebugEnabled()) { + logger.debug("Reusing JDBC Connection [" + ibatisCon + "] for iBATIS operation"); + } + } + } + catch (SQLException ex) { + throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex); + } + + // Execute given callback... + try { + session.startBatch(); + for (T item : items) { + session.update(statementId, item); + } + try { + return session.executeBatchDetailed(); + } catch (BatchException e) { + throw e.getBatchUpdateException(); + } + } + catch (SQLException ex) { + SQLExceptionTranslator sqlStateSQLExceptionTranslator; + + if(dataSource != null) { + sqlStateSQLExceptionTranslator = new SQLStateSQLExceptionTranslator(); + } else { + sqlStateSQLExceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); + } + + throw sqlStateSQLExceptionTranslator.translate("SqlMapClient operation", null, ex); + } + + // Processing finished - potentially session still to be closed. + } + finally { + // Only close SqlMapSession if we know we've actually opened it + // at the present level. + if (ibatisCon == null) { + session.close(); + } + } + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/IbatisPagingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/IbatisPagingItemReader.java index afbf25dfe..6608c3c20 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/IbatisPagingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/IbatisPagingItemReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2013 the original author or authors. + * Copyright 2006-2014 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. @@ -16,16 +16,27 @@ package org.springframework.batch.item.database; +import java.sql.Connection; +import java.sql.SQLException; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; +import javax.sql.DataSource; + import org.springframework.batch.item.ExecutionContext; -import org.springframework.orm.ibatis.SqlMapClientTemplate; +import org.springframework.jdbc.CannotGetJdbcConnectionException; +import org.springframework.jdbc.datasource.DataSourceUtils; +import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; +import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator; +import org.springframework.jdbc.support.SQLExceptionTranslator; +import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import com.ibatis.sqlmap.client.SqlMapClient; +import com.ibatis.sqlmap.client.SqlMapSession; /** *

@@ -67,24 +78,36 @@ import com.ibatis.sqlmap.client.SqlMapClient; * available). *

* + *

Note: This reader was refactored as part of Spring Batch 3.0 to use the iBatis + * APIs directly instead of using Spring's SqlMapClientTemplate as part of the upgrade to + * support Spring 4.

+ * @author Thomas Risberg * @author Dave Syer + * @author Michael Minella * @since 2.0 + * @deprecated as of Spring Batch 3.0, in favor of the native Spring Batch support + * in the MyBatis follow-up project (http://mybatis.github.io/spring/) */ +@Deprecated public class IbatisPagingItemReader extends AbstractPagingItemReader { private SqlMapClient sqlMapClient; private String queryId; - private SqlMapClientTemplate sqlMapClientTemplate; - private Map parameterValues; + private DataSource dataSource; + public IbatisPagingItemReader() { setName(ClassUtils.getShortName(IbatisPagingItemReader.class)); } + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + public void setSqlMapClient(SqlMapClient sqlMapClient) { this.sqlMapClient = sqlMapClient; } @@ -111,12 +134,10 @@ public class IbatisPagingItemReader extends AbstractPagingItemReader { public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); Assert.notNull(sqlMapClient); - sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient); Assert.notNull(queryId); } @Override - @SuppressWarnings("unchecked") protected void doReadPage() { Map parameters = new HashMap(); if (parameterValues != null) { @@ -131,7 +152,89 @@ public class IbatisPagingItemReader extends AbstractPagingItemReader { else { results.clear(); } - results.addAll(sqlMapClientTemplate.queryForList(queryId, parameters)); + results.addAll(execute(parameters)); + } + + @SuppressWarnings("unchecked") + private List execute(Map parameters) { + // We always need to use a SqlMapSession, as we need to pass a Spring-managed + // Connection (potentially transactional) in. This shouldn't be necessary if + // we run against a TransactionAwareDataSourceProxy underneath, but unfortunately + // we still need it to make iBATIS batch execution work properly: If iBATIS + // doesn't recognize an existing transaction, it automatically executes the + // batch for every single statement... + + SqlMapSession session = this.sqlMapClient.openSession(); + if (logger.isDebugEnabled()) { + logger.debug("Opened SqlMapSession [" + session + "] for iBATIS operation"); + } + Connection ibatisCon = null; + + try { + Connection springCon = null; + boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy); + + // Obtain JDBC Connection to operate on... + try { + ibatisCon = session.getCurrentConnection(); + if (ibatisCon == null) { + springCon = (transactionAware ? + dataSource.getConnection() : DataSourceUtils.doGetConnection(dataSource)); + session.setUserConnection(springCon); + if (logger.isDebugEnabled()) { + logger.debug("Obtained JDBC Connection [" + springCon + "] for iBATIS operation"); + } + } + else { + if (logger.isDebugEnabled()) { + logger.debug("Reusing JDBC Connection [" + ibatisCon + "] for iBATIS operation"); + } + } + } + catch (SQLException ex) { + throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex); + } + + // Execute given callback... + try { + return session.queryForList(queryId, parameters); + } + catch (SQLException ex) { + SQLExceptionTranslator sqlStateSQLExceptionTranslator; + + if(dataSource != null) { + sqlStateSQLExceptionTranslator = new SQLStateSQLExceptionTranslator(); + } else { + sqlStateSQLExceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); + } + + throw sqlStateSQLExceptionTranslator.translate("SqlMapClient operation", null, ex); + } + finally { + try { + if (springCon != null) { + if (transactionAware) { + springCon.close(); + } + else { + DataSourceUtils.doReleaseConnection(springCon, dataSource); + } + } + } + catch (Throwable ex) { + logger.debug("Could not close JDBC Connection", ex); + } + } + + // Processing finished - potentially session still to be closed. + } + finally { + // Only close SqlMapSession if we know we've actually opened it + // at the present level. + if (ibatisCon == null) { + session.close(); + } + } } @Override diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisBatchItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisBatchItemWriterTests.java index 82bc1fdec..54a337493 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisBatchItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisBatchItemWriterTests.java @@ -15,7 +15,9 @@ */ package org.springframework.batch.item.database; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -27,7 +29,6 @@ import javax.sql.DataSource; import org.junit.Before; import org.junit.Test; import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.orm.ibatis.SqlMapClientTemplate; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapSession; @@ -42,11 +43,9 @@ public class IbatisBatchItemWriterTests { private IbatisBatchItemWriter writer = new IbatisBatchItemWriter(); private DataSource ds; - - private SqlMapClientTemplate smct; - + private SqlMapClient smc; - + private String statementId = "updateFoo"; @SuppressWarnings("unused") @@ -58,7 +57,7 @@ public class IbatisBatchItemWriterTests { this.id = 1L; this.bar = bar; } - + public Long getId() { return id; } @@ -91,16 +90,16 @@ public class IbatisBatchItemWriterTests { public int hashCode() { return bar.hashCode(); } - + } @Before public void setUp() throws Exception { smc = mock(SqlMapClient.class); ds = mock(DataSource.class); - smct = new SqlMapClientTemplate(ds, smc); writer.setStatementId(statementId); - writer.setSqlMapClientTemplate(smct); + writer.setSqlMapClient(smc); + writer.setDataSource(ds); writer.afterPropertiesSet(); } @@ -122,7 +121,7 @@ public class IbatisBatchItemWriterTests { String message = e.getMessage(); assertTrue("Message does not contain 'SqlMapClient'.", message.indexOf("SqlMapClient") >= 0); } - writer.setSqlMapClientTemplate(smct); + writer.setSqlMapClient(smc); try { writer.afterPropertiesSet(); fail("Expected IllegalArgumentException"); @@ -138,7 +137,7 @@ public class IbatisBatchItemWriterTests { @Test public void testWriteAndFlush() throws Exception { - SqlMapSession sms = mock(SqlMapSession.class); + SqlMapSession sms = mock(SqlMapSession.class); when(smc.openSession()).thenReturn(sms); sms.close(); when(sms.getCurrentConnection()).thenReturn(null); @@ -153,7 +152,7 @@ public class IbatisBatchItemWriterTests { @Test public void testWriteAndFlushWithEmptyUpdate() throws Exception { - SqlMapSession sms = mock(SqlMapSession.class); + SqlMapSession sms = mock(SqlMapSession.class); when(smc.openSession()).thenReturn(sms); sms.close(); when(sms.getCurrentConnection()).thenReturn(null); @@ -177,7 +176,7 @@ public class IbatisBatchItemWriterTests { @Test public void testWriteAndFlushWithFailure() throws Exception { final RuntimeException ex = new RuntimeException("ERROR"); - SqlMapSession sms = mock(SqlMapSession.class); + SqlMapSession sms = mock(SqlMapSession.class); when(smc.openSession()).thenReturn(sms); sms.close(); when(sms.getCurrentConnection()).thenReturn(null); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderAsyncTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderAsyncTests.java index 79f9cbc0c..7dda13cef 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderAsyncTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderAsyncTests.java @@ -25,12 +25,12 @@ import org.springframework.batch.item.sample.Foo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.orm.ibatis.SqlMapClientFactoryBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.jdbc.JdbcTestUtils; import com.ibatis.sqlmap.client.SqlMapClient; -import org.springframework.test.jdbc.JdbcTestUtils; +import com.ibatis.sqlmap.client.SqlMapClientBuilder; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "JdbcPagingItemReaderCommonTests-context.xml") @@ -98,7 +98,7 @@ public class IbatisPagingItemReaderAsyncTests { .newFixedThreadPool(THREAD_COUNT)); for (int i = 0; i < THREAD_COUNT; i++) { completionService.submit(new Callable>() { - @Override + @Override public List call() throws Exception { List list = new ArrayList(); Foo next = null; @@ -130,10 +130,6 @@ public class IbatisPagingItemReaderAsyncTests { } private IbatisPagingItemReader getItemReader() throws Exception { - SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); - factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); - factory.setDataSource(dataSource); - factory.afterPropertiesSet(); SqlMapClient sqlMapClient = createSqlMapClient(); IbatisPagingItemReader reader = new IbatisPagingItemReader(); @@ -141,6 +137,7 @@ public class IbatisPagingItemReaderAsyncTests { reader.setPageSize(2); reader.setSqlMapClient(sqlMapClient); reader.setSaveState(true); + reader.setDataSource(dataSource); reader.afterPropertiesSet(); @@ -148,11 +145,7 @@ public class IbatisPagingItemReaderAsyncTests { } private SqlMapClient createSqlMapClient() throws Exception { - SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); - factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); - factory.setDataSource(dataSource); - factory.afterPropertiesSet(); - return (SqlMapClient) factory.getObject(); + return SqlMapClientBuilder.buildSqlMapClient(new ClassPathResource("ibatis-config.xml", getClass()).getInputStream()); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderCommonTests.java index 8bda98f18..6d5ea1c68 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderCommonTests.java @@ -1,30 +1,27 @@ package org.springframework.batch.item.database; -import org.junit.runners.JUnit4; import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.sample.Foo; import org.springframework.core.io.ClassPathResource; -import org.springframework.orm.ibatis.SqlMapClientFactoryBean; import com.ibatis.sqlmap.client.SqlMapClient; +import com.ibatis.sqlmap.client.SqlMapClientBuilder; @RunWith(JUnit4.class) public class IbatisPagingItemReaderCommonTests extends AbstractDatabaseItemStreamItemReaderTests { - - @Override + + @Override protected ItemReader getItemReader() throws Exception { - SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); - factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); - factory.setDataSource(getDataSource()); - factory.afterPropertiesSet(); SqlMapClient sqlMapClient = createSqlMapClient(); IbatisPagingItemReader reader = new IbatisPagingItemReader(); reader.setQueryId("getPagedFoos"); reader.setPageSize(2); reader.setSqlMapClient(sqlMapClient); + reader.setDataSource(getDataSource()); reader.setSaveState(true); reader.afterPropertiesSet(); @@ -33,14 +30,10 @@ public class IbatisPagingItemReaderCommonTests extends AbstractDatabaseItemStrea } private SqlMapClient createSqlMapClient() throws Exception { - SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); - factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); - factory.setDataSource(getDataSource()); - factory.afterPropertiesSet(); - return (SqlMapClient) factory.getObject(); + return SqlMapClientBuilder.buildSqlMapClient(new ClassPathResource("ibatis-config.xml", getClass()).getInputStream()); } - @Override + @Override protected void pointToEmptyInput(ItemReader tested) throws Exception { IbatisPagingItemReader reader = (IbatisPagingItemReader) tested; reader.close(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderParameterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderParameterTests.java index 265760102..7642ad750 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderParameterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/IbatisPagingItemReaderParameterTests.java @@ -5,28 +5,26 @@ import java.util.Collections; import org.junit.runner.RunWith; import org.springframework.batch.item.sample.Foo; import org.springframework.core.io.ClassPathResource; -import org.springframework.orm.ibatis.SqlMapClientFactoryBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.ibatis.sqlmap.client.SqlMapClient; +import com.ibatis.sqlmap.client.SqlMapClientBuilder; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "/org/springframework/batch/item/database/data-source-context.xml") public class IbatisPagingItemReaderParameterTests extends AbstractPagingItemReaderParameterTests { - @Override + @Override + @SuppressWarnings("deprecation") protected AbstractPagingItemReader getItemReader() throws Exception { - SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); - factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); - factory.setDataSource(dataSource); - factory.afterPropertiesSet(); SqlMapClient sqlMapClient = createSqlMapClient(); IbatisPagingItemReader reader = new IbatisPagingItemReader(); reader.setQueryId("getPagedFoos3AndUp"); reader.setParameterValues(Collections.singletonMap("limit", 3)); reader.setSqlMapClient(sqlMapClient); + reader.setDataSource(dataSource); reader.setSaveState(true); reader.afterPropertiesSet(); @@ -35,11 +33,7 @@ public class IbatisPagingItemReaderParameterTests extends AbstractPagingItemRead } private SqlMapClient createSqlMapClient() throws Exception { - SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); - factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); - factory.setDataSource(dataSource); - factory.afterPropertiesSet(); - return (SqlMapClient) factory.getObject(); + SqlMapClient client = SqlMapClientBuilder.buildSqlMapClient(new ClassPathResource("ibatis-config.xml", getClass()).getInputStream()); + return client; } - } diff --git a/spring-batch-parent/pom.xml b/spring-batch-parent/pom.xml index b201ad2e5..5f66c61b9 100644 --- a/spring-batch-parent/pom.xml +++ b/spring-batch-parent/pom.xml @@ -33,7 +33,7 @@ - 3.2.0.RELEASE + 3.2.7.RELEASE 1.1.2.RELEASE 4.10 1.0.0.RELEASE @@ -552,12 +552,12 @@ com.thoughtworks.xstream xstream - 1.3 + 1.4.4 org.codehaus.jettison jettison - 1.1 + 1.2 stax @@ -565,10 +565,10 @@ - + org.apache.ibatis ibatis-sqlmap - 2.3.0 + 2.3.4.726 true diff --git a/spring-batch-samples/pom.xml b/spring-batch-samples/pom.xml index 93b31e5b0..e7a83f941 100644 --- a/spring-batch-samples/pom.xml +++ b/spring-batch-samples/pom.xml @@ -45,10 +45,10 @@ junit junit - + org.springmodules spring-modules-validation - 0.8 + 0.8a rhino @@ -119,7 +119,7 @@ commons-dbcp commons-dbcp - + com.thoughtworks.xstream xstream diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/FutureDateFunction.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/FutureDateFunction.java deleted file mode 100644 index 47cb1a2c0..000000000 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/FutureDateFunction.java +++ /dev/null @@ -1,55 +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.sample.domain.order.internal.valang; - -import java.util.Date; - -import org.springmodules.validation.valang.functions.AbstractFunction; -import org.springmodules.validation.valang.functions.Function; - - -/** - * Returns Boolean.TRUE if given value is future date, else it returns Boolean.FALSE - * @author peter.zozom - */ -public class FutureDateFunction extends AbstractFunction { - - public FutureDateFunction(Function[] arguments, int line, int column) { - super(arguments, line, column); - definedExactNumberOfArguments(1); - } - - /** - * @see org.springmodules.validation.valang.functions.AbstractFunction#doGetResult(java.lang.Object) - */ - protected Object doGetResult(final Object target) throws Exception { - //get argument - final Object value = getArguments()[0].getResult(target); - - Boolean result; - - if (value instanceof Date) { - final Date now = new Date(System.currentTimeMillis()); - final Date date = (Date) value; - result = (now.compareTo(date) < 0) ? Boolean.TRUE : Boolean.FALSE; - } else { - throw new Exception("No Date value for validation"); - } - - return result; - } -} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/TotalOrderItemsFunction.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/TotalOrderItemsFunction.java deleted file mode 100644 index b541c37ad..000000000 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/TotalOrderItemsFunction.java +++ /dev/null @@ -1,63 +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.sample.domain.order.internal.valang; - -import java.util.List; - -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.AbstractFunction; -import org.springmodules.validation.valang.functions.Function; - - -/** - * Validates total items count in Order. - * - * @author peter.zozom - */ -public class TotalOrderItemsFunction extends AbstractFunction { - public TotalOrderItemsFunction(Function[] arguments, int line, int column) { - super(arguments, line, column); - definedExactNumberOfArguments(2); - } - - /** - * @see org.springmodules.validation.valang.functions.AbstractFunction#doGetResult(java.lang.Object) - */ - @SuppressWarnings("unchecked") - protected Object doGetResult(Object target) throws Exception { - //get arguments - int count = (Integer) getArguments()[0].getResult(target); - Object value = getArguments()[1].getResult(target); - - Boolean result; - - //count items in list of order lines - if (value instanceof List) { - int totalItems = 0; - - for (LineItem lineItem : ((List) value)) { - totalItems += lineItem.getQuantity(); - } - - result = (totalItems == count) ? Boolean.TRUE : Boolean.FALSE; - } else { - throw new Exception("No list for validation"); - } - - return result; - } -} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateDiscountsFunction.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateDiscountsFunction.java deleted file mode 100644 index 38fcc23fb..000000000 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateDiscountsFunction.java +++ /dev/null @@ -1,68 +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.sample.domain.order.internal.valang; - -import java.math.BigDecimal; -import java.util.List; - -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.AbstractFunction; -import org.springmodules.validation.valang.functions.Function; - - -/** - * @author peter.zozom - * - */ -public class ValidateDiscountsFunction extends AbstractFunction { - private static final BigDecimal BD_0 = new BigDecimal(0.0); - private static final BigDecimal BD_PERC_MAX = new BigDecimal(100.0); - - public ValidateDiscountsFunction(Function[] arguments, int line, int column) { - super(arguments, line, column); - definedExactNumberOfArguments(1); - } - - /** - * @see org.springmodules.validation.valang.functions.AbstractFunction#doGetResult(java.lang.Object) - */ - @SuppressWarnings("unchecked") - protected Object doGetResult(Object target) throws Exception { - List lineItems = (List) getArguments()[0].getResult(target); - - for (LineItem item : lineItems) { - - if (BD_0.compareTo(item.getDiscountPerc()) != 0) { - //DiscountPerc must be between 0.0 and 100.0 - if ((BD_0.compareTo(item.getDiscountPerc()) > 0) - || (BD_PERC_MAX.compareTo(item.getDiscountPerc()) < 0) - || (BD_0.compareTo(item.getDiscountAmount()) != 0)) { //only one of DiscountAmount and DiscountPerc should be non-zero - - return Boolean.FALSE; - } - } else { - //DiscountAmount must be between 0.0 and item.price - if ((BD_0.compareTo(item.getDiscountAmount()) > 0) - || (item.getPrice().compareTo(item.getDiscountAmount()) < 0)) { - return Boolean.FALSE; - } - } - } - - return Boolean.TRUE; - } -} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateHandlingPricesFunction.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateHandlingPricesFunction.java deleted file mode 100644 index 29558b768..000000000 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateHandlingPricesFunction.java +++ /dev/null @@ -1,57 +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.sample.domain.order.internal.valang; - -import java.math.BigDecimal; -import java.util.List; - -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.AbstractFunction; -import org.springmodules.validation.valang.functions.Function; - - -/** - * @author peter.zozom - * - */ -public class ValidateHandlingPricesFunction extends AbstractFunction { - private static final BigDecimal BD_MIN = new BigDecimal(0.0); - private static final BigDecimal BD_MAX = new BigDecimal(99999999.99); - - public ValidateHandlingPricesFunction(Function[] arguments, int line, int column) { - super(arguments, line, column); - definedExactNumberOfArguments(1); - } - - /** - * @see org.springmodules.validation.valang.functions.AbstractFunction#doGetResult(java.lang.Object) - */ - @SuppressWarnings("unchecked") - protected Object doGetResult(Object target) throws Exception { - List lineItems = (List) getArguments()[0].getResult(target); - - for (LineItem item : lineItems) { - - if ((BD_MIN.compareTo(item.getHandlingPrice()) > 0) - || (BD_MAX.compareTo(item.getHandlingPrice()) < 0)) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } -} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateIdsFunction.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateIdsFunction.java deleted file mode 100644 index 85f08feb0..000000000 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateIdsFunction.java +++ /dev/null @@ -1,54 +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.sample.domain.order.internal.valang; - -import java.util.List; - -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.AbstractFunction; -import org.springmodules.validation.valang.functions.Function; - - -/** - * @author peter.zozom - * - */ -public class ValidateIdsFunction extends AbstractFunction { - private static final long MAX_ID = 9999999999L; - - public ValidateIdsFunction(Function[] arguments, int line, int column) { - super(arguments, line, column); - definedExactNumberOfArguments(1); - } - - /** - * @see org.springmodules.validation.valang.functions.AbstractFunction#doGetResult(java.lang.Object) - */ - @SuppressWarnings("unchecked") - protected Object doGetResult(Object target) throws Exception { - List lineItems = (List) getArguments()[0].getResult(target); - - for (LineItem item : lineItems) { - - if ((item.getItemId() <= 0) || (item.getItemId() > MAX_ID)) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } -} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidatePricesFunction.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidatePricesFunction.java deleted file mode 100644 index 7157abc86..000000000 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidatePricesFunction.java +++ /dev/null @@ -1,56 +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.sample.domain.order.internal.valang; - -import java.math.BigDecimal; -import java.util.List; - -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.AbstractFunction; -import org.springmodules.validation.valang.functions.Function; - - -/** - * @author peter.zozom - * - */ -public class ValidatePricesFunction extends AbstractFunction { - private static final BigDecimal BD_MIN = new BigDecimal(0.0); - private static final BigDecimal BD_MAX = new BigDecimal(99999999.99); - - public ValidatePricesFunction(Function[] arguments, int line, int column) { - super(arguments, line, column); - definedExactNumberOfArguments(1); - } - - /** - * @see org.springmodules.validation.valang.functions.AbstractFunction#doGetResult(java.lang.Object) - */ - @SuppressWarnings("unchecked") - protected Object doGetResult(Object target) throws Exception { - List lineItems = (List) getArguments()[0].getResult(target); - - for (LineItem item : lineItems) { - - if ((BD_MIN.compareTo(item.getPrice()) > 0) || (BD_MAX.compareTo(item.getPrice()) < 0)) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } -} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateQuantitiesFunction.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateQuantitiesFunction.java deleted file mode 100644 index fbb17e77d..000000000 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateQuantitiesFunction.java +++ /dev/null @@ -1,54 +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.sample.domain.order.internal.valang; - -import java.util.List; - -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.AbstractFunction; -import org.springmodules.validation.valang.functions.Function; - - -/** - * @author peter.zozom - * - */ -public class ValidateQuantitiesFunction extends AbstractFunction { - private static final int MAX_QUANTITY = 9999; - - public ValidateQuantitiesFunction(Function[] arguments, int line, int column) { - super(arguments, line, column); - definedExactNumberOfArguments(1); - } - - /** - * @see org.springmodules.validation.valang.functions.AbstractFunction#doGetResult(java.lang.Object) - */ - @SuppressWarnings("unchecked") - protected Object doGetResult(Object target) throws Exception { - List lineItems = (List) getArguments()[0].getResult(target); - - for (LineItem item : lineItems) { - - if ((item.getQuantity() <= 0) || (item.getQuantity() > MAX_QUANTITY)) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } -} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateShippingPricesFunction.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateShippingPricesFunction.java deleted file mode 100644 index e393a9273..000000000 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateShippingPricesFunction.java +++ /dev/null @@ -1,57 +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.sample.domain.order.internal.valang; - -import java.math.BigDecimal; -import java.util.List; - -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.AbstractFunction; -import org.springmodules.validation.valang.functions.Function; - - -/** - * @author peter.zozom - * - */ -public class ValidateShippingPricesFunction extends AbstractFunction { - private static final BigDecimal BD_MIN = new BigDecimal(0.0); - private static final BigDecimal BD_MAX = new BigDecimal(99999999.99); - - public ValidateShippingPricesFunction(Function[] arguments, int line, int column) { - super(arguments, line, column); - definedExactNumberOfArguments(1); - } - - /** - * @see org.springmodules.validation.valang.functions.AbstractFunction#doGetResult(java.lang.Object) - */ - @SuppressWarnings("unchecked") - protected Object doGetResult(Object target) throws Exception { - List lineItems = (List) getArguments()[0].getResult(target); - - for (LineItem item : lineItems) { - - if ((BD_MIN.compareTo(item.getShippingPrice()) > 0) - || (BD_MAX.compareTo(item.getShippingPrice()) < 0)) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } -} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateTotalPricesFunction.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateTotalPricesFunction.java deleted file mode 100644 index 3bf54744d..000000000 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateTotalPricesFunction.java +++ /dev/null @@ -1,83 +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.sample.domain.order.internal.valang; - -import java.math.BigDecimal; -import java.util.List; - -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.AbstractFunction; -import org.springmodules.validation.valang.functions.Function; - - -/** - * @author peter.zozom - * - */ -public class ValidateTotalPricesFunction extends AbstractFunction { - private static final BigDecimal BD_MIN = new BigDecimal(0.0); - private static final BigDecimal BD_MAX = new BigDecimal(99999999.99); - private static final BigDecimal BD_100 = new BigDecimal(100.00); - - public ValidateTotalPricesFunction(Function[] arguments, int line, int column) { - super(arguments, line, column); - definedExactNumberOfArguments(1); - } - - /** - * @see org.springmodules.validation.valang.functions.AbstractFunction#doGetResult(java.lang.Object) - */ - @SuppressWarnings("unchecked") - protected Object doGetResult(Object target) throws Exception { - List lineItems = (List) getArguments()[0].getResult(target); - - for (LineItem item : lineItems) { - - if ((BD_MIN.compareTo(item.getTotalPrice()) > 0) - || (BD_MAX.compareTo(item.getTotalPrice()) < 0)) { - return Boolean.FALSE; - } - - //calculate total price - - //discount coeficient = (100.00 - discountPerc) / 100.00 - BigDecimal coef = BD_100.subtract(item.getDiscountPerc()) - .divide(BD_100, 4, BigDecimal.ROUND_HALF_UP); - - //discountedPrice = (price * coef) - discountAmount - //at least one of discountPerc and discountAmount is 0 - this is validated by ValidateDiscountsFunction - BigDecimal discountedPrice = item.getPrice().multiply(coef) - .subtract(item.getDiscountAmount()); - - //price for single item = discountedPrice + shipping + handling - BigDecimal singleItemPrice = discountedPrice.add(item.getShippingPrice()) - .add(item.getHandlingPrice()); - - //total price = singleItemPrice * quantity - BigDecimal quantity = new BigDecimal(item.getQuantity()); - BigDecimal totalPrice = singleItemPrice.multiply(quantity) - .setScale(2, BigDecimal.ROUND_HALF_UP); - - //calculatedPrice should equal to item.totalPrice - if (totalPrice.compareTo(item.getTotalPrice()) != 0) { - return Boolean.FALSE; - } - } - - return Boolean.TRUE; - } -} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidator.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidator.java new file mode 100644 index 000000000..d60ec0323 --- /dev/null +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidator.java @@ -0,0 +1,272 @@ +package org.springframework.batch.sample.domain.order.internal.validator; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.springframework.batch.sample.domain.order.Address; +import org.springframework.batch.sample.domain.order.BillingInfo; +import org.springframework.batch.sample.domain.order.Customer; +import org.springframework.batch.sample.domain.order.LineItem; +import org.springframework.batch.sample.domain.order.Order; +import org.springframework.batch.sample.domain.order.ShippingInfo; +import org.springframework.util.StringUtils; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +public class OrderValidator implements Validator { + + private static final List CARD_TYPES = new ArrayList(); + private static final List SHIPPER_IDS = new ArrayList(); + private static final List SHIPPER_TYPES = new ArrayList(); + private static final long MAX_ID = 9999999999L; + private static final BigDecimal BD_MIN = new BigDecimal(0.0); + private static final BigDecimal BD_MAX = new BigDecimal(99999999.99); + private static final BigDecimal BD_PERC_MAX = new BigDecimal(100.0); + private static final int MAX_QUANTITY = 9999; + private static final BigDecimal BD_100 = new BigDecimal(100.00); + + static { + CARD_TYPES.add("VISA"); + CARD_TYPES.add("AMEX"); + CARD_TYPES.add("ECMC"); + CARD_TYPES.add("DCIN"); + CARD_TYPES.add("PAYP"); + + SHIPPER_IDS.add("FEDX"); + SHIPPER_IDS.add("UPS"); + SHIPPER_IDS.add("DHL"); + SHIPPER_IDS.add("DPD"); + + SHIPPER_TYPES.add("STD"); + SHIPPER_TYPES.add("EXP"); + SHIPPER_TYPES.add("AMS"); + SHIPPER_TYPES.add("AME"); + } + + @Override + public boolean supports(Class arg0) { + return arg0.isAssignableFrom(Order.class); + } + + @Override + public void validate(Object arg0, Errors errors) { + Order item = null; + try { + item = (Order) arg0; + } catch (ClassCastException cce) { + errors.reject("Incorrect type"); + } + + if(item != null) { + validateOrder(item, errors); + validateCustomer(item.getCustomer(), errors); + validateAddress(item.getBillingAddress(), errors, "billingAddress"); + validateAddress(item.getShippingAddress(), errors, "shippingAddress"); + validatePayment(item.getBilling(), errors); + validateShipping(item.getShipping(), errors); + validateLineItems(item.getLineItems(), errors); + } + } + + protected void validateLineItems(List lineItems, Errors errors) { + boolean ids = true; + boolean prices = true; + boolean discounts = true; + boolean shippingPrices = true; + boolean handlingPrices = true; + boolean quantities = true; + boolean totalPrices = true; + + for (LineItem lineItem : lineItems) { + if(lineItem.getItemId() <= 0 || lineItem.getItemId() > MAX_ID) { + ids = false; + } + + if((BD_MIN.compareTo(lineItem.getPrice()) > 0) || (BD_MAX.compareTo(lineItem.getPrice()) < 0)) { + prices = false; + } + + if (BD_MIN.compareTo(lineItem.getDiscountPerc()) != 0) { + //DiscountPerc must be between 0.0 and 100.0 + if ((BD_MIN.compareTo(lineItem.getDiscountPerc()) > 0) + || (BD_PERC_MAX.compareTo(lineItem.getDiscountPerc()) < 0) + || (BD_MIN.compareTo(lineItem.getDiscountAmount()) != 0)) { //only one of DiscountAmount and DiscountPerc should be non-zero + discounts = false; + } + } else { + //DiscountAmount must be between 0.0 and item.price + if ((BD_MIN.compareTo(lineItem.getDiscountAmount()) > 0) + || (lineItem.getPrice().compareTo(lineItem.getDiscountAmount()) < 0)) { + discounts = false; + } + } + + if ((BD_MIN.compareTo(lineItem.getShippingPrice()) > 0) || (BD_MAX.compareTo(lineItem.getShippingPrice()) < 0)) { + shippingPrices = false; + } + + if ((BD_MIN.compareTo(lineItem.getHandlingPrice()) > 0) || (BD_MAX.compareTo(lineItem.getHandlingPrice()) < 0)) { + handlingPrices = false; + } + + if ((lineItem.getQuantity() <= 0) || (lineItem.getQuantity() > MAX_QUANTITY)) { + quantities = false; + } + + + if ((BD_MIN.compareTo(lineItem.getTotalPrice()) > 0) + || (BD_MAX.compareTo(lineItem.getTotalPrice()) < 0)) { + totalPrices = false; + } + + //calculate total price + + //discount coeficient = (100.00 - discountPerc) / 100.00 + BigDecimal coef = BD_100.subtract(lineItem.getDiscountPerc()) + .divide(BD_100, 4, BigDecimal.ROUND_HALF_UP); + + //discountedPrice = (price * coef) - discountAmount + //at least one of discountPerc and discountAmount is 0 - this is validated by ValidateDiscountsFunction + BigDecimal discountedPrice = lineItem.getPrice().multiply(coef) + .subtract(lineItem.getDiscountAmount()); + + //price for single item = discountedPrice + shipping + handling + BigDecimal singleItemPrice = discountedPrice.add(lineItem.getShippingPrice()) + .add(lineItem.getHandlingPrice()); + + //total price = singleItemPrice * quantity + BigDecimal quantity = new BigDecimal(lineItem.getQuantity()); + BigDecimal totalPrice = singleItemPrice.multiply(quantity) + .setScale(2, BigDecimal.ROUND_HALF_UP); + + //calculatedPrice should equal to item.totalPrice + if (totalPrice.compareTo(lineItem.getTotalPrice()) != 0) { + totalPrices = false; + } + } + + if(!ids) { + errors.rejectValue("lineItems", "error.lineitems.id"); + } + + if(!prices) { + errors.rejectValue("lineItems", "error.lineitems.price"); + } + + if(!discounts) { + errors.rejectValue("lineItems", "error.lineitems.discount"); + } + + if(!shippingPrices) { + errors.rejectValue("lineItems", "error.lineitems.shipping"); + } + + if(!handlingPrices) { + errors.rejectValue("lineItems", "error.lineitems.handling"); + } + + if(!quantities) { + errors.rejectValue("lineItems", "error.lineitems.quantity"); + } + + if(!totalPrices) { + errors.rejectValue("lineItems", "error.lineitems.totalprice"); + } + } + + protected void validateShipping(ShippingInfo shipping, Errors errors) { + if(!SHIPPER_IDS.contains(shipping.getShipperId())) { + errors.rejectValue("shipping.shipperId", "error.shipping.shipper"); + } + + if(!SHIPPER_TYPES.contains(shipping.getShippingTypeId())) { + errors.rejectValue("shipping.shippingTypeId", "error.shipping.type"); + } + + if(StringUtils.hasText(shipping.getShippingInfo())) { + validateStringLength(shipping.getShippingInfo(), errors, "shipping.shippingInfo", "error.shipping.shippinginfo.length", 100); + } + } + + protected void validatePayment(BillingInfo billing, Errors errors) { + if(!CARD_TYPES.contains(billing.getPaymentId())) { + errors.rejectValue("billing.paymentId", "error.billing.type"); + } + + if(!billing.getPaymentDesc().matches("[A-Z]{4}-[0-9]{10,11}")) { + errors.rejectValue("billing.paymentDesc", "error.billing.desc"); + } + } + + protected void validateAddress(Address address, Errors errors, + String prefix) { + if(address != null) { + if(StringUtils.hasText(address.getAddressee())) { + validateStringLength(address.getAddressee(), errors, prefix + ".addressee", "error.baddress.addresse.length", 60); + } + + validateStringLength(address.getAddrLine1(), errors, prefix + ".addrLine1", "error.baddress.addrline1.length", 50); + + if(StringUtils.hasText(address.getAddrLine2())) { + validateStringLength(address.getAddrLine2(), errors, prefix + ".addrLine2", "error.baddress.addrline2.length", 50); + } + validateStringLength(address.getCity(), errors, prefix + ".city", "error.baddress.city.length", 30); + validateStringLength(address.getZipCode(), errors, prefix + ".zipCode", "error.baddress.zipcode.length", 5); + + if(StringUtils.hasText(address.getZipCode()) && !address.getZipCode().matches("[0-9]{5}")) { + errors.rejectValue(prefix + ".zipCode", "error.baddress.zipcode.format"); + } + + if((!StringUtils.hasText(address.getState()) && ("United States".equals(address.getCountry())) || StringUtils.hasText(address.getState()) && address.getState().length() != 2)) { + errors.rejectValue(prefix + ".state", "error.baddress.state.length"); + } + + validateStringLength(address.getCountry(), errors, prefix + ".country", "error.baddress.country.length", 50); + } + } + + protected void validateStringLength(String string, Errors errors, + String field, String message, int length) { + if(!StringUtils.hasText(string) || string.length() > length) { + errors.rejectValue(field, message); + } + } + + protected void validateCustomer(Customer customer, Errors errors) { + if(!customer.isRegistered() && customer.isBusinessCustomer()) { + errors.rejectValue("customer.registered", "error.customer.registration"); + } + + if(!StringUtils.hasText(customer.getCompanyName()) && customer.isBusinessCustomer()) { + errors.rejectValue("customer.companyName", "error.customer.companyname"); + } + + if(!StringUtils.hasText(customer.getFirstName()) && !customer.isBusinessCustomer()) { + errors.rejectValue("customer.firstName", "error.customer.firstname"); + } + + if(!StringUtils.hasText(customer.getLastName()) && !customer.isBusinessCustomer()) { + errors.rejectValue("customer.lastName", "error.customer.lastname"); + } + + if(customer.isRegistered() && (customer.getRegistrationId() < 0 || customer.getRegistrationId() >= 99999999l)) { + errors.rejectValue("customer.registrationId", "error.customer.registrationid"); + } + } + + protected void validateOrder(Order item, Errors errors) { + if(item.getOrderId() < 0 || item.getOrderId() > 9999999999l) { + errors.rejectValue("orderId", "error.order.id"); + } + + if(new Date().compareTo(item.getOrderDate()) < 0) { + errors.rejectValue("orderDate", "error.order.date.future"); + } + + if(item.getLineItems() != null && item.getTotalLines() != item.getLineItems().size()) { + errors.rejectValue("totalLines", "error.order.lines.badcount"); + } + } +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/IbatisCustomerCreditDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/IbatisCustomerCreditDao.java index 23342431b..d521761b1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/IbatisCustomerCreditDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/IbatisCustomerCreditDao.java @@ -15,25 +15,35 @@ */ package org.springframework.batch.sample.domain.trade.internal; +import java.sql.SQLException; + import org.springframework.batch.sample.domain.trade.CustomerCredit; import org.springframework.batch.sample.domain.trade.CustomerCreditDao; -import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; +import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator; + +import com.ibatis.sqlmap.client.SqlMapClient; /** * @author Lucas Ward * */ -public class IbatisCustomerCreditDao extends SqlMapClientDaoSupport - implements CustomerCreditDao { +public class IbatisCustomerCreditDao implements CustomerCreditDao { + + SqlMapClient sqlMapClient; String statementId; /* (non-Javadoc) * @see org.springframework.batch.sample.domain.trade.internal.CustomerCreditWriter#write(org.springframework.batch.sample.domain.CustomerCredit) */ + @Override public void writeCredit(CustomerCredit customerCredit) { - getSqlMapClientTemplate().update(statementId, customerCredit); + try { + sqlMapClient.update(statementId, customerCredit); + } catch (SQLException e) { + throw new SQLStateSQLExceptionTranslator().translate("SqlMapClient operation", null, e); + } } /* (non-Javadoc) diff --git a/spring-batch-samples/src/main/resources/jobs/iosample/ibatis.xml b/spring-batch-samples/src/main/resources/jobs/iosample/ibatis.xml index 6261739d7..469b94769 100644 --- a/spring-batch-samples/src/main/resources/jobs/iosample/ibatis.xml +++ b/spring-batch-samples/src/main/resources/jobs/iosample/ibatis.xml @@ -8,17 +8,18 @@ class="org.springframework.batch.item.database.IbatisPagingItemReader"> + + - - - - + + + diff --git a/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml b/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml index 56c7f4166..08cdbd7eb 100644 --- a/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/batch - http://www.springframework.org/schema/batch/spring-batch-2.2.xsd + http://www.springframework.org/schema/batch/spring-batch.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> @@ -56,6 +56,7 @@ + @@ -67,4 +68,4 @@ - \ No newline at end of file + diff --git a/spring-batch-samples/src/main/resources/jobs/multilineOrderValidator.xml b/spring-batch-samples/src/main/resources/jobs/multilineOrderValidator.xml index 1ef36c919..0f1df9443 100644 --- a/spring-batch-samples/src/main/resources/jobs/multilineOrderValidator.xml +++ b/spring-batch-samples/src/main/resources/jobs/multilineOrderValidator.xml @@ -1,76 +1,12 @@ - - - - - - 0 AND ? <= 9999999999 : 'Incorrect order ID' : 'error.order.id' } - { orderDate : isFutureDate(?) = FALSE : 'Future date is not allowed' : 'error.order.date.future' } - { totalLines : ? = size(lineItems) : 'Bad count of order lines' : 'error.order.lines.badcount'} - - { customer.registered : customer.businessCustomer = FALSE OR ? = TRUE : 'Business customer must be registered' : 'error.customer.registration'} - { customer.companyName : customer.businessCustomer = FALSE OR ? HAS TEXT : 'Company name for business customer is mandatory' : 'error.customer.companyname'} - { customer.firstName : customer.businessCustomer = TRUE OR ? HAS TEXT : 'Firstname for non-business customer is mandatory' : 'error.customer.firstname'} - { customer.lastName : customer.businessCustomer = TRUE OR ? HAS TEXT : 'Lastname name for non-business customer is mandatory' : 'error.customer.lastname'} - { customer.registrationId : customer.registered = FALSE OR (? > 0 AND ? < 99999999) : 'Incorrect registration ID' : 'error.customer.registrationid'} - - { billingAddress.addressee : ? HAS NO TEXT OR length(?) <= 60 : 'Maximum length for Addressee is 60 characters' : 'error.baddress.addresse.length'} - { billingAddress.addrLine1 : ? HAS TEXT AND length(?) <= 50 : 'Address line1 is mandatory and maximum length for address line1 is 50 characters' : 'error.baddress.addrline1.length'} - { billingAddress.addrLine2 : ? HAS NO TEXT OR length(?) <= 50 : 'Maximum length for address line2 is 50 characters' : 'error.baddress.addrline2.length'} - { billingAddress.city : ? HAS TEXT AND length(?) <= 30 : 'City is mandatory and maximum length for city is 30 characters' : 'error.baddress.city.length'} - { billingAddress.zipCode : ? HAS TEXT AND length(?) <= 50 : 'Zipcode is mandatory and maximum length for zipcode is 5 characters' : 'error.baddress.zipcode.length'} - { billingAddress.zipCode : match('[0-9]{5}',?) = TRUE : 'ZipCode must contain exactly 5 digits' : 'error.baddress.zipcode.format'} - { billingAddress.state : (? HAS NO TEXT AND billingAddress.country != 'United States') OR (? HAS TEXT AND length(?) <= 2) : 'Maximum length for state is 2 characters' : 'error.baddress.state.length'} - { billingAddress.country : ? HAS TEXT AND length(?) <= 50 : 'Country is mandatory and maximum length for country is 50 characters' : 'error.baddress.country.length'} - - { shippingAddress.addressee : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 60) : 'Addressee is mandatory and maximum length for addressee is 60 characters' : 'error.saddress.addresse.length'} - { shippingAddress.addrLine1 : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 50) : 'Address line1 is mandatory and maximum length for address line1 is 50 characters' : 'error.baddress.addrline1.length'} - { shippingAddress.addrLine2 : shippingAddress IS NULL OR (? HAS NO TEXT OR length(?) <= 50) : 'Maximum length for address line2 is 50 characters' : 'error.baddress.addrline2.length'} - { shippingAddress.city : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 30) : 'City is mandatory and maximum length for city is 30 characters' : 'error.baddress.city.length'} - { shippingAddress.zipCode : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 50) : 'Zipcode is mandatory and maximum length for zipcode is 5 characters' : 'error.baddress.zipcode.length'} - { shippingAddress.zipCode : shippingAddress IS NULL OR (match('[0-9]{5}',?) = TRUE) : 'Zipcode must contain exactly 5 digits' : 'error.baddress.zipcode.format'} - { shippingAddress.state : shippingAddress IS NULL OR ((? HAS NO TEXT AND billingAddress.country != 'United States') OR (? HAS TEXT AND length(?) <= 2)) : 'Maximum length for state is 2 characters' : 'error.baddress.state.length'} - { shippingAddress.country : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 50) : 'Country is mandatory and maximum length for country is 50 characters' : 'error.baddress.country.length'} - - { billing.paymentId : ? IN 'VISA','AMEX','ECMC','DCIN','PAYP' : 'Invalid payment type' : 'error.billing.type' } - { billing.paymentDesc : match('[A-Z]{4}-[0-9]{10,11}',?) = TRUE : 'Invalid format of payment description' : 'error.billing.desc' } - - { shipping.shipperId : ? IN 'FEDX', 'UPS', 'DHL', 'DPD' : 'Invalid shipper ID' : 'error.shipping.shipper'} - { shipping.shippingTypeId : ? IN 'STD', 'EXP', 'AMS', 'AME' : 'Invalid shipping type' : 'error.shipping.type' } - { shipping.shippingInfo : ? HAS NO TEXT OR length(?) <= 100 : 'Maximum length for additional shipping info is 100 characters' } - - { lineItems : validateTotalItemsCount(totalItems,?) = TRUE : 'Bad count of total line items' : 'error.lineitems.badcount' } - { lineItems : validateIds(?) = TRUE : 'One or more invalid item IDs' : 'error.lineitems.id' } - { lineItems : validatePrices(?) = TRUE : 'One or more invalid item prices' : 'error.lineitems.price' } - { lineItems : validateDiscounts(?) = TRUE : 'One or more invalid item discounts' : 'error.lineitems.discount' } - { lineItems : validateShippingPrices(?) = TRUE : 'One or more invalid item shipping prices' : 'error.lineitems.shipping' } - { lineItems : validateHandlingPrices(?) = TRUE : 'One or more invalid item handling prices' : 'error.lineitems.handling' } - { lineItems : validateQuantities(?) = TRUE : 'One or more invalid item quantities' : 'error.lineitems.quantity' } - { lineItems : validateTotalPrices(?) = TRUE : 'One or more invalid item total prices' : 'error.lineitems.totalprice' } - ]]> - - - - - - - - - - - - - - - - + - \ No newline at end of file + diff --git a/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml b/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml index 147ae9dd2..f65a418cd 100644 --- a/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml +++ b/spring-batch-samples/src/main/resources/simple-job-launcher-context.xml @@ -3,9 +3,9 @@ xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd - http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> @@ -19,7 +19,7 @@ @@ -48,4 +48,4 @@ - \ No newline at end of file + diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/FutureDateFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/FutureDateFunctionTests.java deleted file mode 100644 index 3348f8adc..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/FutureDateFunctionTests.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.springframework.batch.sample.domain.order.internal.valang; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Date; - -import org.junit.Before; -import org.junit.Test; -import org.springmodules.validation.valang.functions.Function; - -public class FutureDateFunctionTests { - - private FutureDateFunction function; - private Function argument; - - @Before - public void setUp() { - argument = mock(Function.class); - - //create function - function = new FutureDateFunction(new Function[] {argument}, 0, 0); - - } - - @Test - public void testFunctionWithNonDateValue() { - - //set-up mock argument - set return value to non Date value - when(argument.getResult(null)).thenReturn(this); - - //call tested method - exception is expected because non date value - try { - function.doGetResult(null); - fail("Exception was expected."); - } catch (Exception e) { - assertTrue(true); - } - - } - - @Test - public void testFunctionWithFutureDate() throws Exception { - - //set-up mock argument - set return value to future Date - when(argument.getResult(null)).thenReturn(new Date(Long.MAX_VALUE)); - - //vefify result - should be true because of future date - assertTrue((Boolean) function.doGetResult(null)); - - } - - @Test - public void testFunctionWithPastDate() throws Exception { - - //set-up mock argument - set return value to future Date - when(argument.getResult(null)).thenReturn(new Date(0)); - - //vefify result - should be false because of past date - assertFalse((Boolean) function.doGetResult(null)); - - } - -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/TotalOrderItemsFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/TotalOrderItemsFunctionTests.java deleted file mode 100644 index 01edd1766..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/TotalOrderItemsFunctionTests.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.springframework.batch.sample.domain.order.internal.valang; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.Function; - -public class TotalOrderItemsFunctionTests { - - private TotalOrderItemsFunction function; - private Function argument2; - - @Before - public void setUp() { - //create mock for first argument - set count to 3 - Function argument1 = mock(Function.class); - when(argument1.getResult(null)).thenReturn(3); - - - argument2 = mock(Function.class); - - //create function - function = new TotalOrderItemsFunction(new Function[] {argument1, argument2}, 0, 0); - - } - - @Test - public void testFunctionWithNonListValue() { - - when(argument2.getResult(null)).thenReturn(this); - - //call tested method - exception is expected because non list value - try { - function.doGetResult(null); - fail("Exception was expected."); - } catch (Exception e) { - assertTrue(true); - } - - } - - @Test - public void testFunctionWithCorrectItemCount() throws Exception { - - //create list with correct item count - LineItem item = new LineItem(); - item.setQuantity(3); - List list = new ArrayList(); - list.add(item); - - when(argument2.getResult(null)).thenReturn(list); - - //vefify result - assertTrue((Boolean) function.doGetResult(null)); - - } - - @Test - public void testFunctionWithIncorrectItemCount() throws Exception { - - //create list with incorrect item count - LineItem item = new LineItem(); - item.setQuantity(99); - List list = new ArrayList(); - list.add(item); - - when(argument2.getResult(null)).thenReturn(list); - - //vefify result - assertFalse((Boolean) function.doGetResult(null)); - - } - -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateDiscountsFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateDiscountsFunctionTests.java deleted file mode 100644 index ed483349c..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateDiscountsFunctionTests.java +++ /dev/null @@ -1,172 +0,0 @@ -package org.springframework.batch.sample.domain.order.internal.valang; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.Function; - -public class ValidateDiscountsFunctionTests { - - private ValidateDiscountsFunction function; - private Function argument; - - @Before - public void setUp() { - - argument = mock(Function.class); - - //create function - function = new ValidateDiscountsFunction(new Function[] {argument}, 0, 0); - - } - - @Test - public void testDiscountPercentageMin() throws Exception { - - //create line item with correct discount percentage and zero discount amount - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(1.0)); - item.setDiscountAmount(new BigDecimal(0.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all discount percentages are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with negative percentage - item = new LineItem(); - item.setDiscountPerc(new BigDecimal(-1.0)); - item.setDiscountAmount(new BigDecimal(0.0)); - items.add(item); - - //verify result - should be false - second item has invalid discount percentage - assertFalse((Boolean) function.doGetResult(null)); - - } - - @Test - public void testDiscountPercentageMax() throws Exception { - - //create line item with correct discount percentage and zero discount amount - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(99.0)); - item.setDiscountAmount(new BigDecimal(0.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all discount percentages are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with discount percentage above 100 - item = new LineItem(); - item.setDiscountPerc(new BigDecimal(101.0)); - item.setDiscountAmount(new BigDecimal(0.0)); - items.add(item); - - //verify result - should be false - second item has invalid discount percentage - assertFalse((Boolean) function.doGetResult(null)); - - } - - @Test - public void testDiscountPriceMin() throws Exception { - - //create line item with correct discount amount and zero discount percentage - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setDiscountAmount(new BigDecimal(10.0)); - item.setPrice(new BigDecimal(100.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all discount amounts are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with negative discount amount - item = new LineItem(); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setDiscountAmount(new BigDecimal(-1.0)); - item.setPrice(new BigDecimal(100.0)); - items.add(item); - - //verify result - should be false - second item has invalid discount amount - assertFalse((Boolean) function.doGetResult(null)); - - } - - @Test - public void testDiscountPriceMax() throws Exception { - - //create line item with correct discount amount and zero discount percentage - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setDiscountAmount(new BigDecimal(99.0)); - item.setPrice(new BigDecimal(100.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all discount amounts are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with discount amount above item price - item = new LineItem(); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setDiscountAmount(new BigDecimal(101.0)); - item.setPrice(new BigDecimal(100.0)); - items.add(item); - - //verify result - should be false - second item has invalid discount amount - assertFalse((Boolean) function.doGetResult(null)); - - } - - @Test - public void testBothDiscountValuesNonZero() throws Exception { - - //create line item with non-zero discount amount and non-zero discount percentage - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(10.0)); - item.setDiscountAmount(new BigDecimal(99.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be false - only one of the discount values is empty - assertFalse((Boolean) function.doGetResult(null)); - - } - -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateHandlingPricesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateHandlingPricesFunctionTests.java deleted file mode 100644 index 30ddb8086..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateHandlingPricesFunctionTests.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.springframework.batch.sample.domain.order.internal.valang; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.Function; - -public class ValidateHandlingPricesFunctionTests { - - private ValidateHandlingPricesFunction function; - private Function argument; - - @Before - public void setUp() { - argument = mock(Function.class); - - //create function - function = new ValidateHandlingPricesFunction(new Function[] {argument}, 0, 0); - - } - - @Test - public void testHandlingPriceMin() throws Exception { - - //create line item with correct handling price - LineItem item = new LineItem(); - item.setHandlingPrice(new BigDecimal(1.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all handling prices are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with negative handling price - item = new LineItem(); - item.setHandlingPrice(new BigDecimal(-1.0)); - items.add(item); - - //verify result - should be false - second item has invalid handling price - assertFalse((Boolean) function.doGetResult(null)); - - } - - @Test - public void testHandlingPriceMax() throws Exception { - - //create line item with correct handling price - LineItem item = new LineItem(); - item.setHandlingPrice(new BigDecimal(99999999.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all handling prices are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with handling price above allowed max - item = new LineItem(); - item.setHandlingPrice(new BigDecimal(100000000.0)); - items.add(item); - - //verify result - should be false - second item has invalid handling price - assertFalse((Boolean) function.doGetResult(null)); - - } - -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateIdsFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateIdsFunctionTests.java deleted file mode 100644 index c341049d0..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateIdsFunctionTests.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.springframework.batch.sample.domain.order.internal.valang; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.Function; - -public class ValidateIdsFunctionTests { - - private ValidateIdsFunction function; - private Function argument; - - @Before - public void setUp() { - argument = mock(Function.class); - - //create function - function = new ValidateIdsFunction(new Function[] {argument}, 0, 0); - } - - @Test - public void testIdMin() throws Exception { - - //create line item with correct item id - LineItem item = new LineItem(); - item.setItemId(1); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all ids are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with negative id - item = new LineItem(); - item.setItemId(-1); - items.add(item); - - //verify result - should be false - second item has invalid id - assertFalse((Boolean) function.doGetResult(null)); - - } - - @Test - public void testIdMax() throws Exception { - - //create line item with correct item id - LineItem item = new LineItem(); - item.setItemId(9999999999L); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all item ids are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with item id above allowed max - item = new LineItem(); - item.setItemId(10000000000L); - items.add(item); - - //verify result - should be false - second item has invalid item id - assertFalse((Boolean) function.doGetResult(null)); - - } - -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidatePricesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidatePricesFunctionTests.java deleted file mode 100644 index 34251cb61..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidatePricesFunctionTests.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.springframework.batch.sample.domain.order.internal.valang; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.Function; - -public class ValidatePricesFunctionTests { - - private ValidatePricesFunction function; - private Function argument; - - @Before - public void setUp() { - - argument = mock(Function.class); - - //create function - function = new ValidatePricesFunction(new Function[] {argument}, 0, 0); - - } - - @Test - public void testItemPriceMin() throws Exception { - - //create line item with correct item price - LineItem item = new LineItem(); - item.setPrice(new BigDecimal(1.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all item prices are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with negative item price - item = new LineItem(); - item.setPrice(new BigDecimal(-1.0)); - items.add(item); - - //verify result - should be false - second item has invalid item price - assertFalse((Boolean) function.doGetResult(null)); - } - - @Test - public void testItemPriceMax() throws Exception { - - //create line item with correct item price - LineItem item = new LineItem(); - item.setPrice(new BigDecimal(99999999.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all item prices are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with item price above allowed max - item = new LineItem(); - item.setPrice(new BigDecimal(100000000.0)); - items.add(item); - - //verify result - should be false - second item has invalid item price - assertFalse((Boolean) function.doGetResult(null)); - } - -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateQuantitiesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateQuantitiesFunctionTests.java deleted file mode 100644 index 0da1bc597..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateQuantitiesFunctionTests.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.springframework.batch.sample.domain.order.internal.valang; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.Function; - -public class ValidateQuantitiesFunctionTests { - - private ValidateQuantitiesFunction function; - private Function argument; - - @Before - public void setUp() { - - argument = mock(Function.class); - - //create function - function = new ValidateQuantitiesFunction(new Function[] {argument}, 0, 0); - - } - - @Test - public void testQuantityMin() throws Exception { - - //create line item with correct item quantity - LineItem item = new LineItem(); - item.setQuantity(1); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all quantities are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with negative quantity - item = new LineItem(); - item.setQuantity(-1); - items.add(item); - - //verify result - should be false - second item has invalid quantity - assertFalse((Boolean) function.doGetResult(null)); - } - - @Test - public void testQuantityMax() throws Exception { - - //create line item with correct item quantity - LineItem item = new LineItem(); - item.setQuantity(9999); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all item quantities are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with item quantity above allowed max - item = new LineItem(); - item.setQuantity(10000); - items.add(item); - - //verify result - should be false - second item has invalid item quantity - assertFalse((Boolean) function.doGetResult(null)); - } -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateShippingPricesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateShippingPricesFunctionTests.java deleted file mode 100644 index b7a3b5b80..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateShippingPricesFunctionTests.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.springframework.batch.sample.domain.order.internal.valang; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.Function; - -public class ValidateShippingPricesFunctionTests { - - private ValidateShippingPricesFunction function; - private Function argument; - - @Before - public void setUp() { - - argument = mock(Function.class); - - //create function - function = new ValidateShippingPricesFunction(new Function[] {argument}, 0, 0); - - } - - @Test - public void testShippingPriceMin() throws Exception { - - //create line item with correct shipping price - LineItem item = new LineItem(); - item.setShippingPrice(new BigDecimal(1.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all shipping prices are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with negative shipping price - item = new LineItem(); - item.setShippingPrice(new BigDecimal(-1.0)); - items.add(item); - - //verify result - should be false - second item has invalid shipping price - assertFalse((Boolean) function.doGetResult(null)); - - } - - @Test - public void testShippingPriceMax() throws Exception { - - //create line item with correct shipping price - LineItem item = new LineItem(); - item.setShippingPrice(new BigDecimal(99999999.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all shipping prices are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with shipping price above allowed max - item = new LineItem(); - item.setShippingPrice(new BigDecimal(100000000.0)); - items.add(item); - - //verify result - should be false - second item has invalid shipping price - assertFalse((Boolean) function.doGetResult(null)); - - } -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateTotalPricesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateTotalPricesFunctionTests.java deleted file mode 100644 index 626741500..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/valang/ValidateTotalPricesFunctionTests.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.springframework.batch.sample.domain.order.internal.valang; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.sample.domain.order.LineItem; -import org.springmodules.validation.valang.functions.Function; - -public class ValidateTotalPricesFunctionTests { - - private ValidateTotalPricesFunction function; - private Function argument; - - @Before - public void setUp() { - - argument = mock(Function.class); - - //create function - function = new ValidateTotalPricesFunction(new Function[] {argument}, 0, 0); - - } - - @Test - public void testTotalPriceMin() throws Exception { - - //create line item with correct total price - LineItem item = new LineItem(); - item.setDiscountAmount(new BigDecimal(0.0)); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setHandlingPrice(new BigDecimal(0.0)); - item.setShippingPrice(new BigDecimal(0.0)); - item.setPrice(new BigDecimal(1.0)); - item.setQuantity(1); - item.setTotalPrice(new BigDecimal(1.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all total prices are correct - assertTrue((Boolean) function.doGetResult(null)); - - //now add line item with negative item price - item = new LineItem(); - item.setTotalPrice(new BigDecimal(-1.0)); - items.add(item); - - //verify result - should be false - second item has invalid total price - assertFalse((Boolean) function.doGetResult(null)); - } - - @Test - public void testTotalPriceMax() throws Exception { - - //create line item with correct total price - LineItem item = new LineItem(); - item.setDiscountAmount(new BigDecimal(0.0)); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setHandlingPrice(new BigDecimal(0.0)); - item.setShippingPrice(new BigDecimal(0.0)); - item.setPrice(new BigDecimal(99999999.0)); - item.setQuantity(1); - item.setTotalPrice(new BigDecimal(99999999.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all total prices are correct - assertEquals(true, function.doGetResult(null)); - - //now add line item with total price above allowed max - item = new LineItem(); - item.setTotalPrice(new BigDecimal(100000000.0)); - items.add(item); - - //verify result - should be false - second item has invalid total price - assertFalse((Boolean) function.doGetResult(null)); - - } - - @Test - public void testTotalPriceCalculation() throws Exception { - - //create line item - LineItem item = new LineItem(); - item.setDiscountAmount(new BigDecimal(5.0)); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setHandlingPrice(new BigDecimal(1.0)); - item.setShippingPrice(new BigDecimal(2.0)); - item.setPrice(new BigDecimal(250.0)); - item.setQuantity(1); - item.setTotalPrice(new BigDecimal(248.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - when(argument.getResult(null)).thenReturn(items); - - //verify result - should be true - all total prices are correct - assertEquals(true, function.doGetResult(null)); - - //now add line item with incorrect total price - item = new LineItem(); - item.setDiscountAmount(new BigDecimal(5.0)); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setHandlingPrice(new BigDecimal(1.0)); - item.setShippingPrice(new BigDecimal(2.0)); - item.setPrice(new BigDecimal(250.0)); - item.setQuantity(1); - item.setTotalPrice(new BigDecimal(253.0)); - - items.add(item); - - //verify result - should be false - second item has incorrect total price - assertFalse((Boolean) function.doGetResult(null)); - - } - -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidatorTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidatorTests.java new file mode 100644 index 000000000..3d63d14bc --- /dev/null +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidatorTests.java @@ -0,0 +1,340 @@ +package org.springframework.batch.sample.domain.order.internal.validator; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.sample.domain.order.Address; +import org.springframework.batch.sample.domain.order.BillingInfo; +import org.springframework.batch.sample.domain.order.Customer; +import org.springframework.batch.sample.domain.order.LineItem; +import org.springframework.batch.sample.domain.order.Order; +import org.springframework.batch.sample.domain.order.ShippingInfo; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.Errors; + +public class OrderValidatorTests { + + private OrderValidator orderValidator; + + @Before + public void setUp() throws Exception { + orderValidator = new OrderValidator(); + } + + @Test + public void testSupports() { + assertTrue(orderValidator.supports(Order.class)); + } + + @Test + public void testNotAnOrder() { + String notAnOrder = "order"; + Errors errors = new BeanPropertyBindingResult(notAnOrder, "validOrder"); + + orderValidator.validate(notAnOrder, errors); + + assertEquals(1, errors.getAllErrors().size()); + assertEquals("Incorrect type", errors.getAllErrors().get(0).getCode()); + + errors = new BeanPropertyBindingResult(notAnOrder, "validOrder"); + + orderValidator.validate(null, errors); + assertEquals(0, errors.getAllErrors().size()); + } + + @Test + public void testValidOrder() { + Order order = new Order(); + order.setOrderId(-5); + order.setOrderDate(new Date(new Date().getTime() + 1000000000l)); + order.setTotalLines(10); + order.setLineItems(new ArrayList()); + + Errors errors = new BeanPropertyBindingResult(order, "validOrder"); + + orderValidator.validateOrder(order, errors); + + assertEquals(3, errors.getAllErrors().size()); + assertEquals("error.order.id", errors.getFieldError("orderId").getCode()); + assertEquals("error.order.date.future", errors.getFieldError("orderDate").getCode()); + assertEquals("error.order.lines.badcount", errors.getFieldError("totalLines").getCode()); + + order = new Order(); + order.setOrderId(Long.MAX_VALUE); + order.setOrderDate(new Date(new Date().getTime() - 1000)); + order.setTotalLines(0); + List items = new ArrayList(); + items.add(new LineItem()); + order.setLineItems(items); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + + orderValidator.validateOrder(order, errors); + + assertEquals(2, errors.getAllErrors().size()); + assertEquals("error.order.id", errors.getFieldError("orderId").getCode()); + assertEquals("error.order.lines.badcount", errors.getFieldError("totalLines").getCode()); + + order = new Order(); + order.setOrderId(5l); + order.setOrderDate(new Date(new Date().getTime() - 1000)); + order.setTotalLines(1); + items = new ArrayList(); + items.add(new LineItem()); + order.setLineItems(items); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + + orderValidator.validateOrder(order, errors); + + assertEquals(0, errors.getAllErrors().size()); + } + + @Test + public void testValidCustomer() { + Order order = new Order(); + Customer customer = new Customer(); + customer.setRegistered(false); + customer.setBusinessCustomer(true); + order.setCustomer(customer); + + Errors errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateCustomer(customer, errors); + + assertEquals(2, errors.getAllErrors().size()); + assertEquals("error.customer.registration", errors.getFieldError("customer.registered").getCode()); + assertEquals("error.customer.companyname", errors.getFieldError("customer.companyName").getCode()); + + customer = new Customer(); + customer.setRegistered(true); + customer.setBusinessCustomer(false); + customer.setRegistrationId(Long.MIN_VALUE); + order.setCustomer(customer); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateCustomer(customer, errors); + + assertEquals(3, errors.getAllErrors().size()); + assertEquals("error.customer.firstname", errors.getFieldError("customer.firstName").getCode()); + assertEquals("error.customer.lastname", errors.getFieldError("customer.lastName").getCode()); + assertEquals("error.customer.registrationid", errors.getFieldError("customer.registrationId").getCode()); + + customer = new Customer(); + customer.setRegistered(true); + customer.setBusinessCustomer(false); + customer.setRegistrationId(Long.MAX_VALUE); + order.setCustomer(customer); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateCustomer(customer, errors); + + assertEquals(3, errors.getAllErrors().size()); + assertEquals("error.customer.firstname", errors.getFieldError("customer.firstName").getCode()); + assertEquals("error.customer.lastname", errors.getFieldError("customer.lastName").getCode()); + assertEquals("error.customer.registrationid", errors.getFieldError("customer.registrationId").getCode()); + + customer = new Customer(); + customer.setRegistered(true); + customer.setBusinessCustomer(true); + customer.setCompanyName("Acme Inc"); + customer.setRegistrationId(5l); + order.setCustomer(customer); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateCustomer(customer, errors); + + assertEquals(0, errors.getAllErrors().size()); + + customer = new Customer(); + customer.setRegistered(true); + customer.setBusinessCustomer(false); + customer.setFirstName("John"); + customer.setLastName("Doe"); + customer.setRegistrationId(5l); + order.setCustomer(customer); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateCustomer(customer, errors); + + assertEquals(0, errors.getAllErrors().size()); + } + + @Test + public void testValidAddress() { + Order order = new Order(); + + Errors errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateAddress(null, errors, "billingAddress"); + + assertEquals(0, errors.getAllErrors().size()); + + Address address = new Address(); + order.setBillingAddress(address); + + orderValidator.validateAddress(address, errors, "billingAddress"); + + assertEquals(4, errors.getAllErrors().size()); + assertEquals("error.baddress.addrline1.length", errors.getFieldError("billingAddress.addrLine1").getCode()); + assertEquals("error.baddress.city.length", errors.getFieldError("billingAddress.city").getCode()); + assertEquals("error.baddress.zipcode.length", errors.getFieldError("billingAddress.zipCode").getCode()); + assertEquals("error.baddress.country.length", errors.getFieldError("billingAddress.country").getCode()); + + address = new Address(); + address.setAddressee("1234567890123456789012345678901234567890123456789012345678901234567890"); + address.setAddrLine1("123456789012345678901234567890123456789012345678901234567890"); + address.setAddrLine2("123456789012345678901234567890123456789012345678901234567890"); + address.setCity("1234567890123456789012345678901234567890"); + address.setZipCode("1234567890"); + address.setState("1234567890"); + address.setCountry("123456789012345678901234567890123456789012345678901234567890"); + order.setBillingAddress(address); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateAddress(address, errors, "billingAddress"); + + assertEquals(8, errors.getAllErrors().size()); + assertEquals("error.baddress.addresse.length", errors.getFieldError("billingAddress.addressee").getCode()); + assertEquals("error.baddress.addrline1.length", errors.getFieldError("billingAddress.addrLine1").getCode()); + assertEquals("error.baddress.addrline2.length", errors.getFieldError("billingAddress.addrLine2").getCode()); + assertEquals("error.baddress.city.length", errors.getFieldError("billingAddress.city").getCode()); + assertEquals("error.baddress.state.length", errors.getFieldError("billingAddress.state").getCode()); + assertEquals("error.baddress.zipcode.length", errors.getFieldErrors("billingAddress.zipCode").get(0).getCode()); + assertEquals("error.baddress.zipcode.format", errors.getFieldErrors("billingAddress.zipCode").get(1).getCode()); + assertEquals("error.baddress.country.length", errors.getFieldError("billingAddress.country").getCode()); + + address = new Address(); + address.setAddressee("John Doe"); + address.setAddrLine1("123 4th Street"); + address.setCity("Chicago"); + address.setState("IL"); + address.setZipCode("60606"); + address.setCountry("United States"); + order.setBillingAddress(address); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateAddress(address, errors, "billingAddress"); + + assertEquals(0, errors.getAllErrors().size()); + } + + @Test + public void testValidPayment() { + Order order = new Order(); + BillingInfo info = new BillingInfo(); + info.setPaymentId("INVALID"); + info.setPaymentDesc("INVALID"); + order.setBilling(info); + + Errors errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validatePayment(info, errors); + + assertEquals(2, errors.getAllErrors().size()); + assertEquals("error.billing.type", errors.getFieldError("billing.paymentId").getCode()); + assertEquals("error.billing.desc", errors.getFieldError("billing.paymentDesc").getCode()); + + info = new BillingInfo(); + info.setPaymentId("VISA"); + info.setPaymentDesc("ADFI-1234567890"); + order.setBilling(info); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validatePayment(info, errors); + + assertEquals(0, errors.getAllErrors().size()); + } + + @Test + public void testValidShipping() { + Order order = new Order(); + ShippingInfo info = new ShippingInfo(); + info.setShipperId("INVALID"); + info.setShippingTypeId("INVALID"); + order.setShipping(info); + + Errors errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateShipping(info, errors); + + assertEquals(2, errors.getAllErrors().size()); + assertEquals("error.shipping.shipper", errors.getFieldError("shipping.shipperId").getCode()); + assertEquals("error.shipping.type", errors.getFieldError("shipping.shippingTypeId").getCode()); + + info = new ShippingInfo(); + info.setShipperId("FEDX"); + info.setShippingTypeId("EXP"); + info.setShippingInfo("12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + order.setShipping(info); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateShipping(info, errors); + + assertEquals(1, errors.getAllErrors().size()); + assertEquals("error.shipping.shippinginfo.length", errors.getFieldError("shipping.shippingInfo").getCode()); + + info = new ShippingInfo(); + info.setShipperId("FEDX"); + info.setShippingTypeId("EXP"); + info.setShippingInfo("Info"); + order.setShipping(info); + + errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateShipping(info, errors); + + assertEquals(0, errors.getAllErrors().size()); + } + + @Test + public void testValidLineItems() { + Order order = new Order(); + List lineItems = new ArrayList(); + lineItems.add(buildLineItem(-5, 5.00, 0, 0, 2, 3, 3, 30)); + lineItems.add(buildLineItem(Long.MAX_VALUE, 5.00, 0, 0, 2, 3, 3, 30)); + lineItems.add(buildLineItem(6, -5.00, 0, 0, 2, 3, 3, 0)); + lineItems.add(buildLineItem(6, Integer.MAX_VALUE, 0, 0, 2, 3, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, 900, 0, 2, 3, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, -90, 0, 2, 3, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, 10, 20, 2, 3, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, 0, -10, 2, 3, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, 0, 50, 2, 3, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, 0, 0, -2, 3, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, 0, 0, Long.MAX_VALUE, 3, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, 0, 0, 2, -3, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, 0, 0, 2, Long.MAX_VALUE, 3, 30)); + lineItems.add(buildLineItem(6, 5.00, 0, 0, 2, 3, -3, 30)); + lineItems.add(buildLineItem(6, 5.00, 0, 0, 2, 3, Integer.MAX_VALUE, 30)); + lineItems.add(buildLineItem(6, 5.00, 0, 0, 2, 3, 3, -5)); + lineItems.add(buildLineItem(6, 5.00, 0, 0, 2, 3, 3, Integer.MAX_VALUE)); + order.setLineItems(lineItems); + + Errors errors = new BeanPropertyBindingResult(order, "validOrder"); + orderValidator.validateLineItems(lineItems, errors); + + assertEquals(7, errors.getAllErrors().size()); + assertEquals("error.lineitems.id", errors.getFieldErrors("lineItems").get(0).getCode()); + assertEquals("error.lineitems.price", errors.getFieldErrors("lineItems").get(1).getCode()); + assertEquals("error.lineitems.discount", errors.getFieldErrors("lineItems").get(2).getCode()); + assertEquals("error.lineitems.shipping", errors.getFieldErrors("lineItems").get(3).getCode()); + assertEquals("error.lineitems.handling", errors.getFieldErrors("lineItems").get(4).getCode()); + assertEquals("error.lineitems.quantity", errors.getFieldErrors("lineItems").get(5).getCode()); + assertEquals("error.lineitems.totalprice", errors.getFieldErrors("lineItems").get(6).getCode()); + } + + private LineItem buildLineItem(long itemId, double price, int discountPercentage, int discountAmount, long shippingPrice, long handlingPrice, int qty, int totalPrice) { + LineItem invalidId = new LineItem(); + invalidId.setItemId(itemId); + invalidId.setPrice(new BigDecimal(price)); + invalidId.setDiscountPerc(new BigDecimal(discountPercentage)); + invalidId.setDiscountAmount(new BigDecimal(discountAmount)); + invalidId.setShippingPrice(new BigDecimal(shippingPrice)); + invalidId.setHandlingPrice(new BigDecimal(handlingPrice)); + invalidId.setQuantity(qty); + invalidId.setTotalPrice(new BigDecimal(totalPrice)); + return invalidId; + } +}