From 5f80ced21fb63423108bc829cbdbc8168e4b7f0a Mon Sep 17 00:00:00 2001 From: dsyer Date: Sun, 28 Mar 2010 12:03:41 +0000 Subject: [PATCH] Finally: tracked build failure to odd number of items in customer table (after skip sample) --- .../item/database/JdbcPagingItemReader.java | 50 +++++++++---------- .../main/resources/business-schema-hsqldb.sql | 2 +- .../main/resources/data-source-context.xml | 2 +- .../src/main/resources/log4j.properties | 2 +- .../skipSample-job-launcher-context.xml | 8 +-- .../sample/SkipSampleFunctionalTests.java | 8 ++- .../trade/internal/JdbcTradeWriterTests.java | 3 +- .../JdbcPagingRestartIntegrationTests.java | 41 +++++++++++---- 8 files changed, 72 insertions(+), 44 deletions(-) diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java index c0dcbc30f..e01944ca0 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java @@ -19,6 +19,7 @@ package org.springframework.batch.item.database; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -32,7 +33,6 @@ import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.ItemStreamException; import org.springframework.beans.factory.InitializingBean; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; import org.springframework.util.Assert; @@ -179,23 +179,34 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme @Override protected void doReadPage() { - PagingRowCallbackHandler rowCallback = new PagingRowCallbackHandler(); + if (results == null) { + results = new CopyOnWriteArrayList(); + } + else { + results.clear(); + } + + PagingRowMapper rowCallback = new PagingRowMapper(); + + @SuppressWarnings("unchecked") + List query; + if (getPage() == 0) { if (logger.isDebugEnabled()) { logger.debug("SQL used for reading first page: [" + firstPageSql + "]"); } if (parameterValues != null && parameterValues.size() > 0) { if (this.queryProvider.isUsingNamedParameters()) { - simpleJdbcTemplate.getNamedParameterJdbcOperations().query(firstPageSql, + query = simpleJdbcTemplate.getNamedParameterJdbcOperations().query(firstPageSql, getParameterMap(parameterValues, null), rowCallback); } else { - simpleJdbcTemplate.getJdbcOperations().query(firstPageSql, + query = simpleJdbcTemplate.getJdbcOperations().query(firstPageSql, getParameterList(parameterValues, null).toArray(), rowCallback); } } else { - simpleJdbcTemplate.getJdbcOperations().query(firstPageSql, rowCallback); + query = simpleJdbcTemplate.getJdbcOperations().query(firstPageSql, rowCallback); } } @@ -204,22 +215,18 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme logger.debug("SQL used for reading remaining pages: [" + remainingPagesSql + "]"); } if (this.queryProvider.isUsingNamedParameters()) { - simpleJdbcTemplate.getNamedParameterJdbcOperations().query(remainingPagesSql, + query = simpleJdbcTemplate.getNamedParameterJdbcOperations().query(remainingPagesSql, getParameterMap(parameterValues, startAfterValue), rowCallback); } else { - simpleJdbcTemplate.getJdbcOperations().query(remainingPagesSql, + query = simpleJdbcTemplate.getJdbcOperations().query(remainingPagesSql, getParameterList(parameterValues, startAfterValue).toArray(), rowCallback); } } - - if (results == null) { - results = new CopyOnWriteArrayList(); - } - else { - results.clear(); - } - results.addAll(rowCallback.getResults()); + + @SuppressWarnings("unchecked") + Collection result = query; + results.addAll(result); } @@ -301,17 +308,10 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme return parameterList; } - private class PagingRowCallbackHandler implements RowCallbackHandler { - private final List results = new ArrayList(); - - public List getResults() { - return results; - } - - @SuppressWarnings("unchecked") - public void processRow(ResultSet rs) throws SQLException { + private class PagingRowMapper implements RowMapper { + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { startAfterValue = rs.getObject(queryProvider.getSortKey()); - results.add((T) rowMapper.mapRow(rs, results.size())); + return rowMapper.mapRow(rs, rowNum); } } diff --git a/spring-batch-samples/src/main/resources/business-schema-hsqldb.sql b/spring-batch-samples/src/main/resources/business-schema-hsqldb.sql index b02b0b89a..148b0adb3 100644 --- a/spring-batch-samples/src/main/resources/business-schema-hsqldb.sql +++ b/spring-batch-samples/src/main/resources/business-schema-hsqldb.sql @@ -15,7 +15,7 @@ DROP TABLE ERROR_LOG IF EXISTS; CREATE TABLE CUSTOMER_SEQ ( ID BIGINT IDENTITY ); -INSERT INTO CUSTOMER_SEQ (ID) values (5); +INSERT INTO CUSTOMER_SEQ (ID) values (4); CREATE TABLE BATCH_STAGING_SEQ ( ID BIGINT IDENTITY ); diff --git a/spring-batch-samples/src/main/resources/data-source-context.xml b/spring-batch-samples/src/main/resources/data-source-context.xml index 2399ec377..f92799db8 100644 --- a/spring-batch-samples/src/main/resources/data-source-context.xml +++ b/spring-batch-samples/src/main/resources/data-source-context.xml @@ -65,7 +65,7 @@ - + diff --git a/spring-batch-samples/src/main/resources/log4j.properties b/spring-batch-samples/src/main/resources/log4j.properties index 4fc7fe1fc..9e20bcd32 100644 --- a/spring-batch-samples/src/main/resources/log4j.properties +++ b/spring-batch-samples/src/main/resources/log4j.properties @@ -24,7 +24,7 @@ log4j.appender.chainsaw.layout=org.apache.log4j.xml.XMLLayout ### enable spring #log4j.logger.org.springframework=info #log4j.logger.org.springframework.transaction=debug -log4j.logger.org.springframework.jdbc.core=debug +#log4j.logger.org.springframework.jdbc.core=debug #log4j.logger.org.springframework.orm=debug ### debug your specific package or classes with the following example diff --git a/spring-batch-samples/src/main/resources/skipSample-job-launcher-context.xml b/spring-batch-samples/src/main/resources/skipSample-job-launcher-context.xml index d30b8d632..1cb80e575 100644 --- a/spring-batch-samples/src/main/resources/skipSample-job-launcher-context.xml +++ b/spring-batch-samples/src/main/resources/skipSample-job-launcher-context.xml @@ -15,9 +15,6 @@ - - @@ -44,5 +41,10 @@ + + + + + diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java index 5e025afa4..f31bf38a5 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java @@ -25,7 +25,9 @@ import org.springframework.batch.core.repository.JobRestartException; import org.springframework.batch.sample.common.SkipCheckingListener; import org.springframework.batch.sample.domain.trade.internal.TradeWriter; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; +import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.jdbc.SimpleJdbcTestUtils; @@ -49,6 +51,10 @@ public class SkipSampleFunctionalTests { @Autowired private JobOperator jobOperator; + @Autowired + @Qualifier("customerIncrementer") + private DataFieldMaxValueIncrementer incrementer; + @Autowired public void setDataSource(DataSource dataSource) { this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); @@ -59,7 +65,7 @@ public class SkipSampleFunctionalTests { simpleJdbcTemplate.update("DELETE from TRADE"); simpleJdbcTemplate.update("DELETE from CUSTOMER"); for (int i = 1; i < 10; i++) { - simpleJdbcTemplate.update("INSERT INTO CUSTOMER VALUES (" + i + ", 0, 'customer" + i + "', 100000)"); + simpleJdbcTemplate.update("INSERT INTO CUSTOMER (ID, VERSION, NAME, CREDIT) VALUES (" + incrementer.nextIntValue() + ", 0, 'customer" + i + "', 100000)"); } simpleJdbcTemplate.update("DELETE from ERROR_LOG"); } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeWriterTests.java index 7d656fe0f..8f56cb82d 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeWriterTests.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.batch.sample.domain.trade.Trade; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; import org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer; @@ -51,7 +52,7 @@ public class JdbcTradeWriterTests { } @Autowired - public void setIncrementer(AbstractDataFieldMaxValueIncrementer incrementer) { + public void setIncrementer(@Qualifier("incrementerParent") AbstractDataFieldMaxValueIncrementer incrementer) { incrementer.setIncrementerName("TRADE_SEQ"); this.writer.setIncrementer(incrementer); } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JdbcPagingRestartIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JdbcPagingRestartIntegrationTests.java index 062a90d0b..ce5e868b0 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JdbcPagingRestartIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JdbcPagingRestartIntegrationTests.java @@ -19,6 +19,9 @@ package org.springframework.batch.sample.iosample; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import java.util.List; +import java.util.Map; + import javax.sql.DataSource; import org.junit.Test; @@ -51,8 +54,9 @@ public class JdbcPagingRestartIntegrationTests { @Autowired private ItemReader reader; + private SimpleJdbcTemplate jdbcTemplate; - + @Autowired public void setDataSource(DataSource dataSource) { jdbcTemplate = new SimpleJdbcTemplate(dataSource); @@ -65,21 +69,36 @@ public class JdbcPagingRestartIntegrationTests { @Test public void testReader() throws Exception { + + int total = SimpleJdbcTestUtils.countRowsInTable(jdbcTemplate, "CUSTOMER"); + int pageSize = 2; // same as configured in reader + int count = (total / pageSize) * pageSize; + if (count >= pageSize) { + count -= pageSize; + } + ExecutionContext executionContext = new ExecutionContext(); - int count = SimpleJdbcTestUtils.countRowsInTable(jdbcTemplate, "CUSTOMER")-2; executionContext.putInt("JdbcPagingItemReader.read.count", count); // Assume the primary keys are in order - executionContext.putInt("JdbcPagingItemReader.start.after", count); - ((ItemStream)reader).open(executionContext); + + List> ids = jdbcTemplate + .queryForList("SELECT ID, CREDIT FROM CUSTOMER WHERE CREDIT > 10000 ORDER BY ID ASC"); + // System.err.println(ids); + int startAfterValue = ((Long) ids.get(count - 1).get("ID")).intValue(); + // System.err.println("Start after: " + startAfterValue); + executionContext.putInt("JdbcPagingItemReader.start.after", startAfterValue); + ((ItemStream) reader).open(executionContext); + + for (int i = count; i < total; i++) { + CustomerCredit item = reader.read(); + // System.err.println("Item: " + item); + assertNotNull(item); + } + CustomerCredit item = reader.read(); - // System.err.println(item); - assertNotNull(item); - item = reader.read(); - // System.err.println(item); - assertNotNull(item); - item = reader.read(); - // System.err.println(item); + // System.err.println("Item: " + item); assertNull(item); + } }