Java 在 Spring Batch 项目中实现 ItemReader 时如何打开 Reader?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23303581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does one open a Reader when implementing ItemReader in a Spring Batch project?
提问by yamori
In a Spring Batch project I need to compose a record out of multiple lines. I'm implementing ItemReader
to accumulate multiple lines before returning an object. After working through several example projects I have pieced this together but I am faced with a ReaderNotOpenException
.
在 Spring Batch 项目中,我需要用多行组合成一条记录。我正在实现ItemReader
在返回对象之前累积多行。在完成了几个示例项目后,我将它们拼凑在一起,但我面临着ReaderNotOpenException
.
I have triple checked the path to the file is correct. When I debug the delegate
contains the resource and file path from my configuration file.
我已经三重检查了文件的路径是否正确。当我调试delegate
包含我的配置文件中的资源和文件路径时。
Any help appreciated.
任何帮助表示赞赏。
Config file:
配置文件:
<bean id="cvsFileItemReader" class="com.mkyong.XYZFileRecordReader">
<property name="delegate">
<bean class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="classpath:ma/report-headeronly.psv" />
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value="|" />
</bean>
</property>
<property name="fieldSetMapper">
<bean class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper" />
</property>
</bean>
</property>
</bean>
</property>
</bean>
My Reader:
我的读者:
package com.mkyong;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.transform.FieldSet;
import com.mkyong.model.XYZFileHeaderRecord;
public class XYZFileRecordReader implements ItemReader<XYZFileHeaderRecord>, ItemStream {
private FlatFileItemReader<FieldSet> delegate;
@Override
public XYZFileHeaderRecord read() throws Exception,
UnexpectedInputException, ParseException,
NonTransientResourceException {
XYZFileHeaderRecord maFileHeaderRecord = new XYZFileHeaderRecord();
for (FieldSet line = null; (line = this.delegate.read()) != null;) {
String firstToken = line.readString(0);
if (firstToken.equals("File ID")) {
maFileHeaderRecord.setFileName( line.readString(1) );
} else if (firstToken.equals("Date")) {
maFileHeaderRecord.setDate( line.readString(1) );
return maFileHeaderRecord;
}
}
return null;
}
@Override
public void close() throws ItemStreamException {}
@Override
public void open(ExecutionContext arg0) throws ItemStreamException {}
@Override
public void update(ExecutionContext arg0) throws ItemStreamException {}
public FlatFileItemReader<FieldSet> getDelegate() {
return delegate;
}
public void setDelegate(FlatFileItemReader<FieldSet> delegate) {
this.delegate = delegate;
}
}
And my stacktrace:
还有我的堆栈跟踪:
SEVERE: Encountered an error executing the step
org.springframework.batch.item.ReaderNotOpenException: Reader must be open before it can be read.
at org.springframework.batch.item.file.FlatFileItemReader.readLine(FlatFileItemReader.java:195)
at org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:173)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.read(AbstractItemCountingItemStreamItemReader.java:83)
at com.mkyong.XYZFileRecordReader.read(XYZFileRecordReader.java:26)
at com.mkyong.XYZFileRecordReader.read(XYZFileRecordReader.java:1)
at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:91)
at org.springframework.batch.core.step.item.SimpleChunkProvider.read(SimpleChunkProvider.java:155)
at org.springframework.batch.core.step.item.SimpleChunkProvider.doInIteration(SimpleChunkProvider.java:114)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:108)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:395)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:131)
at org.springframework.batch.core.step.tasklet.TaskletStep.doInChunkContext(TaskletStep.java:267)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:253)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:137)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:152)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:131)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:301)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:134)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:127)
at com.mkyong.App.main(App.java:27)
Apr 25, 2014 5:35:56 PM org.springframework.batch.core.launch.support.SimpleJobLauncher run
INFO: Job: [FlowJob: [name=reportJob]] completed with the following parameters: [{}] and the following status: [FAILED]
Exit Status : FAILED
Done
采纳答案by Michael Minella
Your delegate isn't getting opened. The easiest way to address this is to update the open
, close
, and update
methods to call the corresponding methods on the delegate as well. This also allows for restartability (which your current version would not because the state of the delegate is not being saved):
你的代表没有被打开。解决这一问题的最简单的方法是更新open
,close
和update
方法对委托相应的方法调用也是如此。这也允许重新启动(您当前的版本不会,因为未保存委托的状态):
@Override
public void close() throws ItemStreamException {
delegate.close();
}
@Override
public void open(ExecutionContext arg0) throws ItemStreamException {
delegate.open(arg0);
}
@Override
public void update(ExecutionContext arg0) throws ItemStreamException {
delegate.update(arg0);
}
The alternative is to register your FlatFileItemReader
as a stream in your step. You'll have to pull it out to a separate bean definition if you want to go that route.
另一种方法是FlatFileItemReader
在您的步骤中将您注册为流。如果你想走那条路,你必须把它拉到一个单独的 bean 定义中。
You can read more about ItemStream
s and how their lifecycle works and how it is impacted via delegation here: http://docs.spring.io/spring-batch/reference/html-single/index.html#itemStream
您可以ItemStream
在此处阅读有关s 及其生命周期如何工作以及如何通过委托对其产生影响的更多信息:http: //docs.spring.io/spring-batch/reference/html-single/index.html#itemStream
回答by Luca Basso Ricci
You have to call delegate.open() to perform the open of real reader. Or you can register delegate reader as streaming to let SB manage the delegate reader stream lifecycle (read chapter 6.5)
您必须调用 delegate.open() 来执行真正读者的打开。或者您可以将委托阅读器注册为流,让 SB 管理委托阅读器流的生命周期(阅读第 6.5 章)