【问题标题】:Using MultiResourceItemReader to read 2 plain text file and write into single file使用 MultiResourceItemReader 读取 2 个纯文本文件并写入单个文件
【发布时间】:2015-10-29 09:44:53
【问题描述】:

我的批处理作业将生成 2 个文本文件,每行具有字符串格式。我创建了一个阅读器

<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>

我收到了这个错误:

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

基本上我只想合并两个普通文件,并在页脚处附加总数。然后删除两个输入文件。可以帮忙吗?

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;
}

}

【问题讨论】:

  • 你能分享你的“MyWriter”的代码吗?看起来更像是委托属性的错误接口(与所需的 bean 不匹配)
  • 我认为您应该使用 ItemWriter 对象作为 MyWriter.delegate 属性,而不是具体的 FlatFileItemWriter

标签: spring-batch


【解决方案1】:

正如 Luca Basso Ricci 已经指出的那样,问题在于您在 MyWriter 中的委托定义。由于 Spring 为其 bean 创建代理,它不会将您的 FlatFileItemReader 识别为 FlatFileItemWriter 的实际实例,因此 setDelegate(FlatFileItemWriter delegate) 将失败。

在 MyWriter 中使用 ItemStreamWriter。正如您在异常消息中看到的,创建的代理确实提供了此接口。因此,它可以插入

这将解决委托写入、打开、关闭和更新方法。为了编写页眉和页脚,您需要实现一个 HeaderCallback 和 FooterCallback 并直接在您的 FlatFileItemWriter 的定义中设置它。

实现 HeaderCallback 不是问题,因为您只设置了 systemdate。

作为FooterCallback,制作你自己的Bean。在 FlatFileItemWriter 中使用它来编写页脚。向它添加一个“increaseCount”方法并在您的 MyWriter Bean 中使用它来增加写入计数。

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

【讨论】:

    【解决方案2】:

    另一个可能的选择是直接从 FlatFileItemWriter 扩展 MyWriter:

    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();
    }   
    

    }

    您的 XML 中的配置如下所示:

    <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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 2020-04-26
      • 2016-08-14
      • 2012-05-24
      • 2021-01-23
      • 2015-05-23
      相关资源
      最近更新 更多