无法使用Spring批处理写入FlatFile

时间:2016-09-11 15:51:33

标签: spring spring-batch

您好我想在生成的平面文件中添加标题,因此决定添加标题回调。但是我收到以下错误。

    org.springframework.beans.factory.BeanCreationException: Error 
    creating bean with name 'scopedTarget.reportItemWriter' defined in 
    class    path resource [spring/batch/jobs/equity-eod-job.xml]:        
    Initialization of bean failed; nested 
    exception 
    is org.springframework.beans.ConversionNotSupportedException: 

    Failed to    convert property value of type 'com.sun.proxy.$Proxy8   

    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.$Proxy8 implementing 
   org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,org.spring  framework.beans.factory.InitializingBean,org.springframework.batch.item.ItemStre  amWriter,org.springframework.batch.item.ItemStream,org.springframework.aop.scope      .ScopedObject,java.io.Serializable,org.springframework.aop.framework.AopInfrastr  uctureBean,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
    at    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:529)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at 
               org.springframework.beans.factory.support.AbstractBeanFactory$2.
    getObject
    (AbstractBeanFactory.java:331)

    at org.springframework.batch.core.scope.StepScope.get(StepScope.java:113)
    at                        
    org.springframework.beans.factory.support.AbstractBeanFactory.
    doGetBean
   (Abstract    BeanFactory.java:327)
    at    org.springframework.beans.factory.support.AbstractBeanFactory.getBean
(AbstractBeanFactory.java:191)
    at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:34)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:184)
    at com.sun.proxy.$Proxy6.open(Unknown Source)
    at 

请帮帮我:

我的步骤:

 <batch:step id="generateReport" next="sendMailStep">
        <batch:tasklet>
            <batch:chunk reader="reportReader" writer="reportItemWriter"
                 commit-interval="100">
            </batch:chunk>
        </batch:tasklet>
    </batch:step>

阅读器:               

编剧:

<bean id="csvFileWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
    <property name="resource" value="file:./resources/#{jobParameters['REPORT']}"></property>
    <property name="lineAggregator">
        <bean
            class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
            <property name="delimiter" value=","></property>
            <property name="fieldExtractor">
                <bean
                    class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
                    <property name="names"
                        value="symbol,date,openPrice,highPrice,lowPrice,closePrice,trueRange,isInsideDayFormed,narrowRange"></property>
                </bean>
            </property>
        </bean>
    </property>
                    <property name="headerCallback" ref="reportItemWriter"></property>
</bean>

<bean id="reportItemWriter" class="com.equities.batch.ReportWriter" scope="step">
<property name="delegate" ref="csvFileWriter"></property>
</bean>

报告撰稿人:

package com.equities.batch;

import java.io.IOException;
import java.io.Writer;
import java.util.List;

import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamSupport;
import org.springframework.batch.item.ItemStreamWriter;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.file.FlatFileHeaderCallback;
import org.springframework.batch.item.file.FlatFileItemWriter;

import com.equities.pojo.EodDataBean;

public class ReportWriter implements      ItemWriter<EodDataBean>,FlatFileHeaderCallback,ItemStream{

private FlatFileItemWriter<EodDataBean> delegate;


/* (non-Javadoc)
 * @see org.springframework.batch.item.file.FlatFileHeaderCallback#writeHeader(java.io.Writer)
 */
public void writeHeader(Writer writer) throws IOException {
    writer.write("Script"+","+","+"Date"+","+"Open"+","+"High"+","+"Low"+","+"Close"+","+"True range"+","+"ID"+","+"NR");       
}

/* (non-Javadoc)
 * @see org.springframework.batch.item.ItemWriter#write(java.util.List)
 */
public void write(List<? extends EodDataBean> items) throws Exception {
    this.delegate.write(items);     
}

/**
 * @return the delegate
 */
public ItemWriter<EodDataBean> getDelegate() {
    return delegate;
}

/**
 * @param delegate the delegate to set
 */
public void setDelegate(FlatFileItemWriter<EodDataBean> delegate) {
    this.delegate =  delegate;
}

/* (non-Javadoc)
 * @see org.springframework.batch.item.ItemStream#open(org.springframework.batch.item.ExecutionContext)
 */
public void open(ExecutionContext executionContext)
        throws ItemStreamException {
    delegate.open(executionContext);
}

/* (non-Javadoc)
 * @see org.springframework.batch.item.ItemStream#update(org.springframework.batch.item.ExecutionContext)
 */
public void update(ExecutionContext executionContext)
        throws ItemStreamException {
    delegate.update(executionContext);

}

/* (non-Javadoc)
 * @see org.springframework.batch.item.ItemStream#close()
 */
public void close() throws ItemStreamException {
    delegate.close();

}

}

如果我删除ItemStream并将编写器设置为ItemStream,则会出现以下错误。

SEVERE: Encountered an error executing step generateReport in job     eodBatchJob
rg.springframework.batch.item.WriterNotOpenException: Writer must be open  
before it can be written to
at 

org.springframework.batch.item.file.FlatFileItemWriter.write
(FlatFileItemWriter.java:255)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

1 个答案:

答案 0 :(得分:3)

当定义了Spring中的Beans时,它们通常可以构建为Proxy,而不是定义类的真实实例。

例如,这发生在bean“csvFileWriter”的代码中,因为它是用作用域“step”定义的。 Spring只会为它创建一个代理,并将实例的实际构造推迟到实际执行步骤的位置。

问题是你的“setDelegate”需要一个FlatFileItemWriter,但是,它只获取一个代理而不是一个实际上是“FlatFileItemWriter”或派生自“FlatFileItemWriter”的类的实例。

Proxy类可以“模拟”类的实现接口,但是它们不能模拟类本身。在您的示例中,代理可以伪装成“ItemWriter”,“ItemStream”和“ItemStreamWriter”,因为此接口实际上是由FlatFileItemWriter实现的,但是,如上所述,它不能伪装成“FlatFileItemWriter”。 / p>

因此,如果您在ReportWriter中更改以下内容,则代码应该起作用:

for folderName, subfolders, filenames in os.walk('C:\\FOLDER'):
print('The current folder is ' + folderName)
for subfolder in subfolders:
    print('SUBFOLDER OF ' + folderName + ': ' + subfolder)
for filename in filenames:
    print('FILE INSIDE ' + folderName + ': '+ filename)

但是,没有理由创建自己的“ReportWriter”并设置委托。相反,只需定义一个ReportHeaderCallBack类并使用它在FlatFileItemWriter中配置headercallback:

public class ReportWriter implements      ItemWriter<EodDataBean>,FlatFileHeaderCallback,ItemStream{

    private ItemStreamWriter<EodDataBean> delegate;

    /**
     * @param delegate the delegate to set
     */
    public void setDelegate(ItemStreamWriter<EodDataBean> delegate) {
        this.delegate =  delegate;
    }

   ...

我想,这也是Nghia Do在评论中提出的解决方案。