当前位置: 首页 > 知识库问答 >
问题:

使用CompositeItemWriter和Classifier的Spring批处理发出CompositeItemWriter

梁丘逸仙
2023-03-14

我使用spring批处理从数据库中读取数据(使用分区),并根据输入键-1,2,3,4将数据写入一组文件。

我创建了一个CompositeItemWriter,它是两个ClassifierCompositeItemWriter的组合。即使我已将单个Writer注册为stream,但仍然会遇到以下异常:

org.springframework.batch.item.WriterNotOpenException: Writer must be open before it can be written to

我甚至尝试将ItemWriter1和ItemWriter2注册为流,但这给了我一个不同的错误:

Caused by: java.lang.IllegalStateException: Cannot convert value of type [com.sun.proxy.$Proxy13 implementing org.springframework.batch.item.ItemWriter,java.io.Serializable,org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.batch.item.ItemStream] for property 'streams[0]': no matching editors or conversion strategy found
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:264)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:128)
    at org.springframework.beans.TypeConverterDelegate.convertToTypedArray(TypeConverterDelegate.java:463)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:195)
    at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:448)
    ... 74 more
public class WriterA1 implements ItemWriter<List<Object>>, ItemStream {
...
}
<job id="abcJob" xmlns="http://www.springframework.org/schema/batch"
    restartable="true"> 

    <step id="masterStep">
        <partition step="slaveStep" partitioner="abcPartitioner">
            <handler grid-size="${grid-size}" task-executor="abcTaskExecutor" />
        </partition>            
    </step> 

</job>

<step id="slaveStep" xmlns="http://www.springframework.org/schema/batch">
        <tasklet transaction-manager="transactionManager">
            <chunk reader="abcReader" writer="abcWriter"
                processor="abcProcessor" commit-interval="${a}" skip-limit="${b}" retry-limit="${c}" >

                <streams>
                    <!-- 
                    <stream ref="ItemWriter1"/> 
                    <stream ref="ItemWriter2"/>
                     -->                        
                    <stream ref="WriterA1"/>
                    <stream ref="WriterB2"/>
                    <stream ref="WriterC3"/>
                    <stream ref="WriterD4"/>                                            
                    <stream ref="WriterA5"/>
                    <stream ref="WriterB6"/>
                    <stream ref="WriterC7"/>
                    <stream ref="WriterD8"/> 

                </streams>                

            </chunk>
            <listeners>
                ...                                     
            </listeners>                                                
        </tasklet>              
    </step> 


<bean id="abcWriter" class="org.springframework.batch.item.support.CompositeItemWriter" scope="step">
    <property name="delegates">
        <list>              
            <ref bean="ItemWriter1" />
            <ref bean="ItemWriter2" /> 
        </list>
    </property>
</bean>  

<bean id="ItemWriter1" class="org.springframework.batch.item.support.ClassifierCompositeItemWriter" scope="step">
    <property name="classifier">
        <bean
            class="org.springframework.classify.BackToBackPatternClassifier">
            <property name="routerDelegate">
                <bean class="xxx.xxx.xxx.xxx.Classifier1" scope="step"/>
            </property>
            <property name="matcherMap">
                <map>
                     <entry key="1" value-ref="WriterA1" />
                     <entry key="2" value-ref="WriterB2" />
                     <entry key="3" value-ref="WriterC3" />
                     <entry key="4" value-ref="WriterD4" />
                </map>
            </property>
        </bean>     
    </property>
</bean>

<bean id="ItemWriter2" class="org.springframework.batch.item.support.ClassifierCompositeItemWriter" scope="step">
    <property name="classifier">
        <bean
            class="org.springframework.classify.BackToBackPatternClassifier">
            <property name="routerDelegate">
                <bean class="xxx.xxx.xxx.xxx.Classifier2" scope="step"/>
            </property>
            <property name="matcherMap">
                <map>
                     <entry key="1" value-ref="WriterA5" />
                     <entry key="2" value-ref="WriterB6" />
                     <entry key="3" value-ref="WriterC7" />
                     <entry key="4" value-ref="WriterD8" />
                </map>
            </property>
        </bean>     
    </property>
</bean>

 <bean id="WriterA1" class="xxx.xxx.xxx.xxx.WriterA1" scope="step">

 </bean>
 <bean id="WriterB2" class="xxx.xxx.xxx.xxx.WriterB2" scope="step">

 </bean>
<bean id="WriterC3" class="xxx.xxx.xxx.xxx.WriterC3" scope="step">

</bean>
<bean id="WriterD4" class="xxx.xxx.xxx.xxx.WriterD4" scope="step">

</bean>
  <bean id="WriterA5" class="xxx.xxx.xxx.xxx.WriterA5" scope="step">

  </bean>
  <bean id="WriterB6" class="xxx.xxx.xxx.xxx.WriterB6" scope="step">

  </bean>
 <bean id="WriterC7" class="xxx.xxx.xxx.xxx.WriterC7" scope="step">

 </bean>
 <bean id="WriterD8" class="xxx.xxx.xxx.xxx.WriterD8" scope="step">

 </bean>

请指教。

共有1个答案

顾俊茂
2023-03-14

你有三种类型的作家。从上到下:

>

  • abcWriter是一个CompositeItemWriter。它通过将ItemStream方法调用委托给委托(这里是ItemWriter1ItemWriter2)来实现ItemStream,前提是它们实现了ItemStream。事实并非如此。但是,即使他们实现了itemstream,您也不应该在步骤配置中将itemwriter1itemwriter2单独注册为流(下一个要点中还有另一个独立的原因)。

    ItemWriter1/ItemWriter2分类器组合ItemWriter。该类不实现itemstream,因此您不能在步骤配置中将它们注册为流。

  •  类似资料:
    • 我有一个compositeItemWriter,它有2个代理编写器:1。HeaderWriter将一些字段从我的对象写入头表2。DetailWriter将文件写入详细表。 context.xml:

    • 我有一个场景,它遵循以下步骤: 1。读者将从表a中得到一个列表a。 2。处理器处理列表A以返回对象A和MimeMessage。 3.writer将对象A写入表B中,并使用MimeMessage发送邮件。 我可以在上面的场景中使用CompositeItemProcessor和CompositeItemWriter吗?如果是,我如何在步骤配置中设置输出对象,以及如何定义发送邮件的ItemWriter将

    • 我有一个Spring批处理作业,它通过SFTP从远程Linux服务器检索文件。远程服务器上的目录是一个包含七天文件(约400个文件)的存档。文件的大小相对较小。 Spring批处理知道哪些文件已经被处理。 当我启动应用程序时。第一次,Spring Batch tasklet检索文件时,Spring Batch会为它已经处理的每个文件生成一个异常: > 在Transformer类中,是否应该检查文件

    • 我有以下工作要处理在一定的时间间隔或特别的基础上。 作业中的步骤如下: 我也想要用户界面,在那里我可以触发一个特别的基础上的工作,而且我应该能够提供参数从用户界面。 我想用Spring batch来完成这个任务,但它更多的是用于读->处理->写之类的工作。这里,在第一步中,我正在生成由第二步读取的数据。我不确定我是否还可以使用Spring batch来实现这个,或者有更好的方法来实现这个。

    • 我有一个spring批处理应用程序,它从文件中读取数据,进行一些处理,最后编写一个定制的输出。这一切都是一步到位的。在下一步中,我将使用一个tasklet来归档输入文件(移动到另一个文件夹)。这个应用程序运行良好。但是,现在我需要在远程服务器上对sftp输出文件进行进一步处理。我找到了一种使用spring integration实现sftp的方法,在这里我创建了一个输入通道,该通道将反馈给outb