BATCH-1615: modified XML and flat file readers to throw new exception

This commit is contained in:
dsyer
2010-09-07 10:51:14 +00:00
parent c7491971eb
commit b78c0db130
7 changed files with 149 additions and 8 deletions

View File

@@ -21,8 +21,7 @@ package org.springframework.batch.item;
*
* Implementations are expected to be stateful and will be called multiple times
* for each batch, with each call to {@link #read()} returning a different value
* and finally returning <code>null</code> when all input data is
* exhausted.<br/>
* and finally returning <code>null</code> when all input data is exhausted.<br/>
*
* Implementations need *not* be thread safe and clients of a {@link ItemReader}
* need to be aware that this is the case.<br/>
@@ -44,8 +43,16 @@ public interface ItemReader<T> {
* twice from successive calls (or otherwise), if the first call was in a
* transaction that rolled back.
*
* @throws Exception if an underlying resource is unavailable.
* @throws ParseException if there is a problem parsing the current record
* (but the next one may still be valid)
* @throws NonTransientResourceException if there is a fatal exception in
* the underlying resource. After throwing this exception implementations
* should endeavour to return null from subsequent calls to read.
* @throws UnexpectedInputException if there is an uncategorised problem
* with the input data. Assume potentially transient, so subsequent calls to
* read might succeed.
* @throws Exception if an there is a non-specific error.
*/
T read() throws Exception, UnexpectedInputException, ParseException;
T read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException;
}

View File

@@ -0,0 +1,46 @@
/*
* 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.item;
/**
* Exception indicating that an error has been encountered doing I/O from a
* reader, and the exception should be considered fatal.
*
* @author Dave Syer
*/
public class NonTransientResourceException extends ItemReaderException {
/**
* Create a new {@link NonTransientResourceException} based on a message and
* another exception.
*
* @param message the message for this exception
* @param cause the other exception
*/
public NonTransientResourceException(String message, Throwable cause) {
super(message, cause);
}
/**
* Create a new {@link NonTransientResourceException} based on a message.
*
* @param message the message for this exception
*/
public NonTransientResourceException(String message) {
super(message);
}
}

View File

@@ -223,7 +223,10 @@ public class FlatFileItemReader<T> extends AbstractItemCountingItemStreamItemRea
line = applyRecordSeparatorPolicy(line);
}
catch (IOException e) {
throw new FlatFileParseException("Unable to read from resource: [" + resource + "]", e, line, lineCount);
// Prevent IOException from recurring indefinitely
// if client keeps catching and re-calling
noInput = true;
throw new NonTransientFlatFileException("Unable to read from resource: [" + resource + "]", e, line, lineCount);
}
return line;
}

View File

@@ -0,0 +1,55 @@
/*
* 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.item.file;
import org.springframework.batch.item.NonTransientResourceException;
/**
* Exception thrown when errors are encountered with the underlying resource.
*
* @author Dave Syer
*/
public class NonTransientFlatFileException extends NonTransientResourceException {
private String input;
private int lineNumber;
public NonTransientFlatFileException(String message, String input) {
super(message);
this.input = input;
}
public NonTransientFlatFileException(String message, String input, int lineNumber) {
super(message);
this.input = input;
this.lineNumber = lineNumber;
}
public NonTransientFlatFileException(String message, Throwable cause, String input, int lineNumber) {
super(message, cause);
this.input = input;
this.lineNumber = lineNumber;
}
public String getInput() {
return input;
}
public int getLineNumber() {
return lineNumber;
}
}

View File

@@ -136,8 +136,12 @@ public class StaxEventItemReader<T> extends AbstractItemCountingItemStreamItemRe
*
* @return <code>true</code> if next fragment was found, <code>false</code>
* otherwise.
*
* @throws DataAccessResourceFailureException if the cursor could not be
* moved. This will be treated as fatal and subsequent calls to read will
* return null.
*/
protected boolean moveCursorToNextFragment(XMLEventReader reader) {
protected boolean moveCursorToNextFragment(XMLEventReader reader) throws DataAccessResourceFailureException {
try {
while (true) {
while (reader.peek() != null && !reader.peek().isStartElement()) {
@@ -215,7 +219,16 @@ public class StaxEventItemReader<T> extends AbstractItemCountingItemStreamItemRe
T item = null;
if (moveCursorToNextFragment(fragmentReader)) {
boolean success = false;
try {
success = moveCursorToNextFragment(fragmentReader);
}
catch (DataAccessResourceFailureException e) {
// Prevent caller from retrying indefinitely since this is fatal
noInput = true;
throw e;
}
if (success) {
fragmentReader.markStartFragment();
@SuppressWarnings("unchecked")