diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/MultiResourceItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/MultiResourceItemReader.java index 125fc0c38..d27c39d44 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/MultiResourceItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/MultiResourceItemReader.java @@ -1,8 +1,8 @@ package org.springframework.batch.item; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; @@ -33,11 +33,13 @@ public class MultiResourceItemReader extends ExecutionContextUserSupport impleme private List itemBuffer = new ArrayList(); - private Iterator itemBufferIterator = null; + private ListIterator itemBufferIterator = null; private boolean shouldReadBuffer = false; private boolean saveState = false; + + private int lastMarkedBufferIndex = 0; public MultiResourceItemReader() { setName(MultiResourceItemReader.class.getSimpleName()); @@ -84,9 +86,15 @@ public class MultiResourceItemReader extends ExecutionContextUserSupport impleme * @see ItemReader#mark() */ public void mark() throws MarkFailedException { + if (!shouldReadBuffer) { + itemBuffer.clear(); + itemBufferIterator = null; + lastMarkedBufferIndex = 0; + } + else { + lastMarkedBufferIndex = itemBufferIterator.nextIndex(); + } delegate.mark(); - itemBuffer.clear(); - shouldReadBuffer = false; } /** @@ -96,7 +104,7 @@ public class MultiResourceItemReader extends ExecutionContextUserSupport impleme */ public void reset() throws ResetFailedException { shouldReadBuffer = true; - itemBufferIterator = itemBuffer.listIterator(); + itemBufferIterator = itemBuffer.listIterator(lastMarkedBufferIndex); } /** diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java index 1d4f62cb9..9e682c96a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java @@ -512,6 +512,8 @@ public class JdbcCursorItemReader extends ExecutionContextUserSupport implements private int INITIAL_POSITION = -1; + private int lastMarkedIndex; + public BufferredResultSetReader(ResultSet rs, RowMapper rowMapper, int processedRowCount) { Assert.notNull(rs, "The ResultSet must not be null"); Assert.notNull(rowMapper, "The RowMapper must not be null"); @@ -519,6 +521,7 @@ public class JdbcCursorItemReader extends ExecutionContextUserSupport implements this.rowMapper = rowMapper; buffer = new ArrayList(); currentIndex = INITIAL_POSITION; + lastMarkedIndex = INITIAL_POSITION; this.processedRowCount = processedRowCount; } @@ -536,7 +539,7 @@ public class JdbcCursorItemReader extends ExecutionContextUserSupport implements if (!rs.next()) { return null; } - int currentRow = processedRowCount + 1;// rs.getRow(); + int currentRow = processedRowCount + 1; buffer.add(rowMapper.mapRow(rs, currentRow)); verifyCursorPosition(currentRow); } @@ -550,13 +553,19 @@ public class JdbcCursorItemReader extends ExecutionContextUserSupport implements } public void mark() throws MarkFailedException { - buffer.clear(); - currentIndex = INITIAL_POSITION; + if (currentIndex == buffer.size()) { + buffer.clear(); + currentIndex = INITIAL_POSITION; + lastMarkedIndex = INITIAL_POSITION; + } + else { + lastMarkedIndex = currentIndex; + } } public void reset() throws ResetFailedException { - processedRowCount -= buffer.size(); - currentIndex = INITIAL_POSITION; + processedRowCount -= currentIndex - lastMarkedIndex; + currentIndex = lastMarkedIndex; } /** diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemReader.java index c9279cb68..c3126aa96 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemReader.java @@ -3,8 +3,8 @@ package org.springframework.batch.item.xml; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; @@ -61,9 +61,11 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements private boolean saveState = false; - private List buffer = new ArrayList(); + private List itemBuffer = new ArrayList(); - private Iterator bufferIterator = null; + private ListIterator itemBufferIterator = null; + + private int lastMarkedBufferIndex = 0; /** * indicates the reader has been shouldReadBuffer and should read items from @@ -90,13 +92,13 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements // read from buffer after rollback if (shouldReadBuffer) { - if (bufferIterator.hasNext()) { - return bufferIterator.next(); + if (itemBufferIterator.hasNext()) { + return itemBufferIterator.next(); } else { // buffer is exhausted, continue reading from file shouldReadBuffer = false; - bufferIterator = null; + itemBufferIterator = null; } } @@ -108,7 +110,7 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements fragmentReader.markFragmentProcessed(); } - buffer.add(item); + itemBuffer.add(item); if (item == null) { currentRecordCount--; } @@ -118,7 +120,8 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements public void close(ExecutionContext executionContext) { initialized = false; currentRecordCount = 0; - clearBuffer(); + itemBuffer.clear(); + itemBufferIterator = null; try { if (fragmentReader != null) { fragmentReader.close(); @@ -262,9 +265,17 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements * @see org.springframework.batch.item.AbstractItemReader#mark() */ public void mark() { + + if (!shouldReadBuffer) { + itemBuffer.clear(); + itemBufferIterator = null; + lastMarkedBufferIndex = 0; + } + else { + lastMarkedBufferIndex = itemBufferIterator.nextIndex(); + } + lastCommitPointRecordCount = currentRecordCount; - clearBuffer(); - shouldReadBuffer = false; } /* @@ -275,7 +286,7 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements public void reset() { currentRecordCount = lastCommitPointRecordCount; shouldReadBuffer = true; - bufferIterator = buffer.listIterator(); + itemBufferIterator = itemBuffer.listIterator(lastMarkedBufferIndex); fragmentReader.reset(); } @@ -290,11 +301,5 @@ public class StaxEventItemReader extends ExecutionContextUserSupport implements this.saveState = saveState; } - /** - * Clear the buffer and release the iterator. - */ - private void clearBuffer() { - buffer.clear(); - bufferIterator = null; - } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemReaderTests.java index 3b0c9714c..88853b6e7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/CommonItemReaderTests.java @@ -64,12 +64,12 @@ public abstract class CommonItemReaderTests extends TestCase { assertEquals(foo2, tested.read()); // TODO handle shortening the commit interval on the fly -// -// tested.mark(); -// -// assertEquals(foo3, tested.read()); -// -// tested.reset(); + + tested.mark(); + + assertEquals(foo3, tested.read()); + + tested.reset(); assertEquals(foo3, tested.read());