[英]Spring Boot batch - MultiResourceItemReader : move to next file on error
In a batch service, I read multiple XML files using a MultiResourceItemReader, which delegate to a StaxEventItemReader. 在批处理服务中,我使用MultiResourceItemReader读取了多个XML文件,该文件委托给StaxEventItemReader。
If an error is raised reading a file (a parsing exception for example), I would like to specify to Spring to start reading the next matching file. 如果在读取文件时出现错误(例如解析异常),我想指定给Spring开始读取下一个匹配的文件。 Using @OnReadError annotation and/or a SkipPolicy for example.
例如,使用@OnReadError注释和/或SkipPolicy。
Currently, when a reading exception is raised, the batch stops. 当前,当出现读取异常时,该批处理将停止。
Does anyone have an idea how to do it ? 有人知道怎么做吗?
EDIT: I see MultiResourceItemReader has a method readNextItem(), but it's private -_- 编辑:我看到MultiResourceItemReader有一个方法readNextItem(),但它是私有的-_-
I'm not using SB for a while, but looking MultiResourceItemReader
code I suppose you can write your own ResourceAwareItemReaderItemStream
wrapper where you check for a flag setted to move to next file or to perform a standard read using a delegate. 我有一段时间没有使用SB了,但是我想看一下
MultiResourceItemReader
代码,我想您可以编写自己的ResourceAwareItemReaderItemStream
包装器,在其中检查设置为移至下一个文件或使用委托执行标准读取的标志。
This flag can be stored into execution-context or into your wrapper and should be cleared after a move next. 该标志可以存储在执行上下文中或包装中,并且应在下一步移动后清除。
class MoveNextReader<T> implements ResourceAwareItemReaderItemStream<T> {
private ResourceAwareItemReaderItemStream delegate;
private boolean skipThisFile = false;
public void setSkipThisFile(boolean value) {
skipThisFile = value;
}
public void setResource(Resource resource) {
skipThisFile = false;
delegate.setResource(resource);
}
public T read() {
if(skipThisFile) {
skipThisFile = false;
// This force MultiResourceItemReader to move to next resource
return null;
}
return delegate.read();
}
}
Use this class as delegate for MultiResourceItemReader
and in @OnReadError
inject MoveNextReader
and set MoveNextReader.skipThisFile
. 使用此类作为
MultiResourceItemReader
委托,并在@OnReadError
注入MoveNextReader
并设置MoveNextReader.skipThisFile
。
I can't test code from myself but I hope this can be a good starting point. 我无法自己测试代码,但我希望这可以成为一个好的起点。
Here are my final classes to read multiple XML files and jump to the next file when a read error occurs on one (thanks to Luca's idea). 这是我的最后一个类,用于读取多个XML文件并在一个文件发生读取错误时跳转到下一个文件(这要归功于Luca的想法)。
My custom ItemReader, extended from MultiResourceItemReader : 我的自定义ItemReader,从MultiResourceItemReader扩展:
public class MyItemReader extends MultiResourceItemReader<InputElement> {
private SkippableResourceItemReader<InputElement> reader;
public MyItemReader() throws IOException {
super();
// Resources
PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
this.setResources( resourceResolver.getResources( "classpath:input/inputFile*.xml" ) );
// Delegate reader
reader = new SkippableResourceItemReader<InputElement>();
StaxEventItemReader<InputElement> delegateReader = new StaxEventItemReader<InputElement>();
delegateReader.setFragmentRootElementName("inputElement");
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
unmarshaller.setClassesToBeBound( InputElement.class );
delegateReader.setUnmarshaller( unmarshaller );
reader.setDelegate( delegateReader );
this.setDelegate( reader );
}
[...]
@OnReadError
public void onReadError( Exception exception ){
reader.setSkipResource( true );
}
}
And the ItemReader-in-the-middle used to skip the current resource : 中间的ItemReader用于跳过当前资源:
public class SkippableResourceItemReader<T> implements ResourceAwareItemReaderItemStream<T> {
private ResourceAwareItemReaderItemStream<T> delegate;
private boolean skipResource = false;
@Override
public void close() throws ItemStreamException {
delegate.close();
}
@Override
public T read() throws UnexpectedInputException, ParseException, NonTransientResourceException, Exception {
if( skipResource ){
skipResource = false;
return null;
}
return delegate.read();
}
@Override
public void setResource( Resource resource ) {
skipResource = false;
delegate.setResource( resource );
}
@Override
public void open( ExecutionContext executionContext ) throws ItemStreamException {
delegate.open( executionContext );
}
@Override
public void update( ExecutionContext executionContext ) throws ItemStreamException {
delegate.update( executionContext );
}
public void setDelegate(ResourceAwareItemReaderItemStream<T> delegate) {
this.delegate = delegate;
}
public void setSkipResource( boolean skipResource ) {
this.skipResource = skipResource;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.