Using MultiResourceItemReader to read 2 plain text file and write into single file

蓝咒 提交于 2019-12-08 04:41:17

问题


My batch job will generate 2 text files with string format per line. I created a reader

<bean id="myMultiResourceReader"
    class=" org.springframework.batch.item.file.MultiResourceItemReader">
    <property name="resources" value="file:D:/MY/sample/*.txt" />
</bean> 
<bean id="myFinalWriter" class="org.springframework.batch.item.file.FlatFileItemWriter"
    scope="step">
    <property name="resource" value="${test.file3}" />
    <property name="lineAggregator">
        <bean
            class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
    </property>
    <property name="footerCallback" ref="myFinalCustomItemWriter" />
    <property name="headerCallback" ref="myFinalCustomItemWriter" />
</bean>
<bean id="myFinalCustomItemWriter" class="my.process.MyWriter"
    scope="step">
    <property name="delegate" ref="myFinalWriter" />
    <property name="stepContext" value="#{stepExecution.stepName}" />
</bean>

I was getting this error:

Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'com.sun.proxy.$Proxy68 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,org.springframework.batch.item.ItemStreamWriter,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'org.springframework.batch.item.file.FlatFileItemWriter' for property 'delegate'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [com.sun.proxy.$Proxy68 implementing org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.springframework.beans.factory.InitializingBean,org.springframework.batch.item.ItemStreamWriter,org.springframework.batch.item.ItemStream,org.springframework.aop.scope.ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.file.FlatFileItemWriter] for property 'delegate': no matching editors or conversion strategy found

Basically I just want to combine two plain file, and append the total count at footer. Then delete away the both input file. Can help?

MyWriter.java

public class MyWriter implements ItemWriter<String>, FlatFileFooterCallback, FlatFileHeaderCallback, ItemStream{
private static Logger log = Logger.getLogger(MyWriter.class);
private FlatFileItemWriter<String> delegate;
private int recordCount = 0;
private String stepContext;

public void writeFooter(Writer writer) throws IOException {
    writer.write("#" + recordCount);
}

public void writeHeader(Writer writer) throws IOException {
    writer.write("#" + StringUtil.getSysDate());
}

public void setDelegate(FlatFileItemWriter<String> delegate) {
    this.delegate = delegate;
}

public void write(List<? extends String> list) throws Exception {
     int chunkRecord = 0;
    for (String item : list) {
        chunkRecord++;
    }
    delegate.write(list);
    recordCount += chunkRecord;
}

public void close() throws ItemStreamException {
    this.delegate.close();
}

public void open(ExecutionContext arg0) throws ItemStreamException {
    this.delegate.open(arg0);
}

public void update(ExecutionContext arg0) throws ItemStreamException {
    this.delegate.update(arg0);
}

public void setStepContext(String stepContext) {
    this.stepContext = stepContext;
}

}


回答1:


As Luca Basso Ricci already pointed out, the problem is your delegate definition in MyWriter. Since Spring creates proxies for it beans, it will not recognize your FlatFileItemReader as an actual instance of FlatFileItemWriter and, therefore, the setDelegate(FlatFileItemWriter delegate) will fail.

Use an ItemStreamWriter in MyWriter. As you see in the exception message, the created proxy does provide this interface. Hence, it can be inserted

This will solve the delegation to write, open, close, and update method. In order to write the header and footer, you need to implement a HeaderCallback and FooterCallback and set it directly in the definition of your FlatFileItemWriter.

Implementing the HeaderCallback is not a problem since you only set the systemdate.

As FooterCallback, make your own Bean. Use it in the FlatFileItemWriter to write the footer. Add an "increaseCount" method to it and use it in your MyWriter Bean to increase the written count.

public void write(List<? extends String> list) throws Exception {
    myFooterCallback.increaseCount(list.size());
    delegate.write(list);
}



回答2:


Another possible option would be to directly extend MyWriter from FlatFileItemWriter:

public class MyWriter extends FlatFileItemWriter<String> implements FlatFileFooterCallback, FlatFileHeaderCallback{
private static Logger log = Logger.getLogger(MyWriter.class);

private int recordCount = 0;
private String stepContext;

public void writeFooter(Writer writer) throws IOException {
    writer.write("#" + recordCount);
}

public void writeHeader(Writer writer) throws IOException {
    writer.write("#" + StringUtil.getSysDate());
}

public void afterPropertiesSet() {
  setFooterCallback(this);
  setHeaderCallback(this);
  super.afterPropertiesSet();
}

public void write(List<? extends String> list) throws Exception {
    super.write(list);
    recordCount += list.size();
}   

}

Configuration in your XML would look like this:

<bean id="myFinalCustomItemWriter" class="my.process.MyWriter" scope="step">
    <property name="resource" value="${test.file3}" />
    <property name="lineAggregator">
        <bean        class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
    </property>
    <property name="stepContext" value="#{stepExecution.stepName}" />
</bean>


来源:https://stackoverflow.com/questions/33410722/using-multiresourceitemreader-to-read-2-plain-text-file-and-write-into-single-fi

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!