From cf066740080321522e6b4d767db3a43cf423db7c Mon Sep 17 00:00:00 2001 From: lucasward Date: Mon, 5 Oct 2009 04:03:12 +0000 Subject: [PATCH] BATCH-1418: StaxEventItemReader now controls restart itself. --- .../batch/item/xml/StaxEventItemReader.java | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) 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 b66866640..35a4c674e 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 @@ -22,7 +22,9 @@ import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.EndElement; import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -211,5 +213,49 @@ public class StaxEventItemReader extends AbstractItemCountingItemStreamItemRe return item; } - + + /* + * jumpToItem is overridden because reading in and attempting to bind an entire fragment + * is unacceptable in a restart scenario, and may cause exceptions to be thrown that + * were already skipped in previous runs. + */ + @Override + protected void jumpToItem(int itemIndex) throws Exception { + for (int i = 0; i < itemIndex; i++) { + readToStartFragement(); + readToEndFragment(); + } + } + + /* + * Read until the first StartElement tag that matches the provided + * fragmentRootElementName. Because there may be any number of tags in between where the reader + * is now and the fragment start, this is done in a loop until the element type and name + * match. + */ + private void readToStartFragement() throws XMLStreamException{ + while(true){ + XMLEvent nextEvent = eventReader.nextEvent(); + if( nextEvent.isStartElement() && + ((StartElement)nextEvent).getName().getLocalPart().equals(fragmentRootElementName)){ + return; + } + } + } + + /* + * Read until the first EndElement tag that matches the provided + * fragmentRootElementName. Because there may be any number of tags in between where the reader + * is now and the fragment end tag, this is done in a loop until the element type and name + * match + */ + private void readToEndFragment() throws XMLStreamException{ + while(true){ + XMLEvent nextEvent = eventReader.nextEvent(); + if( nextEvent.isEndElement() && + ((EndElement)nextEvent).getName().getLocalPart().equals(fragmentRootElementName)){ + return; + } + } + } }