Search code examples
spring-bootspring-integrationspring-integration-file

Spring Integration upgrade from 5.2.x to 5.3 problem


I wanted to upgrade Spring boot version from 2.2.7.RELEASE to 2.3.0.RELEASE, I am using also Spring integration file with XML configuration (see below). when starting my application, a NullPointerException is thrown. After debugging the issue, the root cause was the creation of the bean file:inbound-channel-adapter. The interesting thing is that only this type of beans which cause this issue and all other ones doesn't. Did anyone had a similar issue? Anyone can help transforming this XML to Java configuration style? Thanks in advance.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:task="http://www.springframework.org/schema/task"
       xmlns:file="http://www.springframework.org/schema/integration/file"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
       http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
       http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">


    <bean id="compositeFilter" class="org.springframework.integration.file.filters.CompositeFileListFilter">
        <constructor-arg>
            <list>
                <ref bean="ignoreHiddenFileListFilter"/>
                <ref bean="acceptOnceFileListFilter"/>
                <ref bean="extensionFileFilter"/>
            </list>
        </constructor-arg>
    </bean>

    <!-- upload folder listener  -->
    <file:inbound-channel-adapter id="uploadFilesScanner" directory="${integration.upload-folder}" filter="compositeFilter">
        <int:poller fixed-rate="${integration.poller-rate:10000}"/>
    </file:inbound-channel-adapter>

    <file:outbound-gateway request-channel="uploadFilesScanner" reply-channel="batchFilesScanner" directory="${integration.directory}" delete-source-files="true"/>

    <!-- 1) Scan for files -->
    <file:inbound-channel-adapter id="batchFilesScanner" directory="${integration.directory}" filter="compositeFilter">
        <int:poller fixed-rate="5000"/>
    </file:inbound-channel-adapter>

    <!-- 2) move the file to processing -->
    <file:outbound-gateway request-channel="batchFilesScanner" reply-channel="batchFilesProcessing" directory="${integration.processing-folder}" delete-source-files="true"/>

    <!-- 3) transform csv file -->
    <int:service-activator input-channel="batchFilesProcessing" output-channel="batchFilesTran" ref="batchTransformerTask" method="execute"/>

    <!-- 4) move the file to archive folder -->
    <file:outbound-gateway request-channel="batchFilesTran" reply-channel="batchFilesArchive" directory="${integration.archive-folder}" delete-source-files="true"/>

    <int:service-activator input-channel="batchFilesArchive" ref="cleanupHelper" method="execute"/>

    <!-- Transformer task channel configuration -->
    <task:executor id="batchFilesTranTaskExecutor" pool-size="1" rejection-policy="CALLER_RUNS" queue-capacity="1"/>
    <int:channel id="batchFilesTran">
        <int:dispatcher load-balancer="round-robin" task-executor="batchFilesTranTaskExecutor" failover="false"/>
    </int:channel>

    <int:service-activator input-channel="errorChannel" ref="intErrorHandler" method="execute"/>

</beans>

NullPointerException:

Caused by:
        java.lang.NullPointerException
            at org.springframework.integration.support.utils.IntegrationUtils.obtainComponentName(IntegrationUtils.java:205)
            at org.springframework.integration.graph.IntegrationGraphServer$NodeFactory.sourceNode(IntegrationGraphServer.java:399)
            at org.springframework.integration.graph.IntegrationGraphServer.lambda$pollingAdapters$1(IntegrationGraphServer.java:216)
            at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
            at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
            at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
            at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
            at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
            at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
            at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
            at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
            at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
            at org.springframework.integration.graph.IntegrationGraphServer.pollingAdapters(IntegrationGraphServer.java:221)
            at org.springframework.integration.graph.IntegrationGraphServer.buildGraph(IntegrationGraphServer.java:184)
            at org.springframework.integration.graph.IntegrationGraphServer.onApplicationEvent(IntegrationGraphServer.java:116)
            at org.springframework.integration.graph.IntegrationGraphServer.onApplicationEvent(IntegrationGraphServer.java:67)
            at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
            at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
            at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
            at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:403)
            at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:360)
            at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:897)
            at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553)
            at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
            at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
            at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
            at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
            at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
            at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
            ... 88 more


Solution

  • The issue is confirmed. The FileReadingMessageSourceFactoryBean doesn't populate a beanName into a FileReadingMessageSource it produces.

    Your config is too big to convert it over here immediately. Consider to follow docs: https://docs.spring.io/spring-integration/docs/current/reference/html/overview.html#programming-tips

    A Java & Annotations configuration analog for the <file:inbound-channel-adapter> is like this:

    @Bean
    @InboundChannelAdapter
    public FileReadingMessageSource fileReadingMessageSource() {
    
    ...
    }
    

    See more info here: https://docs.spring.io/spring-integration/docs/current/reference/html/configuration.html#annotations

    With Java DSL it is just a matter to take an IntegrationFlows.from(MessageSource) factory and follow its builder for the rest:

    https://docs.spring.io/spring-integration/docs/current/reference/html/dsl.html#java-dsl-inbound-adapters