Search code examples
genericsdependency-injectionspring-batchautowiredxml-configuration

Spring 3.2 - how to inject FlatFileItemWriter configured in XML to parameterized property in java class


We have a current application that uses a FlatFileItemWriter configured in XML to produce a fixed length record file ("FileItemWriter"). We want to add second ItemWriter as a Java class that will process the same chunks to update a hstory table in the DB ("HistoryItemWriter"). A third Java ItemWriter ("DispatcherItemWriter") has been imnplemented to call each of these guys in turn, passing the chunk.

The problem is injecting the reference to the FlatFileItemWriter configured in XML to a FlatFileItemWriter property in the DispatcherItemWriter class. The log shows the bean reference being retrieved but it then throws a ConversionNotSupportedexception (log snippet below).

The FlatFileItemWriter property in the DispatcherItemWriter Java class was defined as parameterized, but there is no way to similarly denote parameterization in XML, though at least one post suggests this is possible in 4.0 (which is not an option for now).

I've tried a variety of approaches using @Autowired, @Resource and no annotation, coupled with defining the property with and without parameterization, and also have tried both 'p:fileItemWriter-ref="fileItemWriter"' on the bean and 'property name="fileItemWriter" ref="fileItemWriter"' within the bean. Spring finds the bean ok, but always fails with "no matching editors or conversion strategy found".

Has anyone accomplished this in 3.2?

Here is the fileItemWriter configuration:

<bean id="fileItemWriter" 
    class="org.springframework.batch.item.file.FlatFileItemWriter" 
    scope="step">
    <property  name="resource" value="file:${strRunFileName}" /> 
    <property  name="lineAggregator">
    . . . etc.
    </property >
</bean>

Here is the dispatcherItemWriter bean configuration:

<bean id="dispatcherItemWriter" 
    class="com.xyz.DispatcherItemWriter" 
    scope="step">
    <property name="fileItemWriter" ref="fileItemWriter" />
</bean>

Here is the historyItemWriter configuration:

<bean id="historyItemWriter" 
    class="com.xyz.HistoryItemWriter" 
    scope="step" 
    p:dataSource-ref="dataSource" />    

Here is the variable declaration in the HistoryItemWriter class:

    @Component
    public class RejectItemWriter implements ItemWriter<RejectResult> {
        // fileItemWriter is defined in module-context.xml
        @SuppressWarnings("rawtypes")
        // @Autowired
        @Resource(name="fileItemWriter")
        // private FlatFileItemWriter <Result> fileItemWriter;
        private FlatFileItemWriter fileItemWriter;

Here is the Tasklet:

<batch:tasklet>
    <batch:chunk 
        reader="itemReader" 
        processor="ItemProcessor" 
        writer="dispatcherItemWriter" 
        commit-interval="1000" />
</batch:tasklet>

And here is the relevant part of the log:

16:31:48.342 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 
Returning cached instance of singleton bean 'fileItemWriter'
16:31:48.342 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - 
Failed to convert bean 'fileItemWriter' 
to required type 
[org.springframework.batch.item.file.FlatFileItemWriter]
org.springframework.beans.ConversionNotSupportedException: 
Failed to convert value of type 'sun.proxy.$Proxy10 implementing 
org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,
org.springframework.beans.factory.InitializingBean,
org.springframework.batch.item.ItemWriter,
org.springframework.batch.item.ItemStream,
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.file.FlatFileItemWriter'; 
nested exception is java.lang.IllegalStateException: 
Cannot convert value of type [sun.proxy.$Proxy10 implementing 
org.springframework.batch.item.file.ResourceAwareItemWriterItemStream,
org.springframework.beans.factory.InitializingBean,
org.springframework.batch.item.ItemWriter,
org.springframework.batch.item.ItemStream,
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.file.FlatFileItemWriter]: 
no matching editors or conversion strategy found

Note that org.springframework.batch.item.ItemWriter is in the list of implemented interfaces, and all the interfaces and implementing classes are parameterized.


Solution

  • No need to create DispatchItemWriter, spring batch already implemented the uses case you are looking for, use CompositeItemWriter. You can look for the example here