在进一步处理之前等待jdbc出站通道适配器完成

时间:2018-04-24 12:40:09

标签: jdbc spring-integration

我是Spring Integration的新手,我正在试验一个小项目中的各种组件。

在手头的任务中,我需要处理一个文本文件并将其内容存储到数据库中。该文件包含可以组合在一起的行,因此将每个文件分成几个独立的消息是很自然的。

这是整个过程(请参见最后的配置):

  1. 进行初始文件分析;
    • transformers.outcomeTransf
    • 完成
  2. 将一些数据存储到数据库(即文件名,文件日期等);
  3. 将文件内容拆分为几个不同的消息;
    • splitters.outcomeSplit
    • 完成
  4. 进一步分析每条消息;
    • transformers.SingleoutcomeToMap
    • 完成
  5. 将单个消息数据存储到数据库引用步骤1中存储的数据。
    • stored-proc-outbound-channel-adapter
    • 完成
  6. 数据库只包含两个表:

    • T1用于文件元数据(文件名,文件日期,文件来源,......);
    • T2表示文件内容详细信息,此处的行引用T1中的行。

    我缺少第2步的组件。据我所知,通道出站适配器“吞下”它处理的消息,因此没有其他端点可以接收它。

    在第一步之后我想到了一个发布 - 订阅频道(没有TaskExecutor),其中 jdbc出站适配器作为第一个订阅者和来自的分离器第3个作为第二个:每个订阅的处理程序应该接收消息的副本,但是我不清楚分割器中的任何处理是否会等待出站适配器完成。

    这是完成任务的正确方法吗?如果步骤4中的变换器被异步调用怎么办 - 每个分裂的消息都是自包含的,并且会调用并发性。

    Spring配置:

    <?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:int-file="http://www.springframework.org/schema/integration/file"
        xmlns:int-jdbc="http://www.springframework.org/schema/integration/jdbc"
        xmlns:beans="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/integration
                http://www.springframework.org/schema/integration/spring-integration.xsd
                http://www.springframework.org/schema/integration/file
                http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
                http://www.springframework.org/schema/integration/jdbc
                http://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- input-files-from-folder -->
        <int-file:inbound-channel-adapter id="outcomeIn" 
                                      directory="file:/in-outcome">
            <int:poller id="poller" fixed-delay="2500" />
        </int-file:inbound-channel-adapter>
    
        <int:transformer input-channel="outcomeIn" output-channel="outcomesChannel" method="transform">
            <beans:bean class="transformers.outcomeTransf" />
        </int:transformer>
    
        <!--  save source to db! -->
    
        <int:splitter input-channel="outcomesChannel" output-channel="singleoutcomeChannel" method="splitMessage">
            <beans:bean class="splitters.outcomeSplit" />
        </int:splitter>
    
        <int:transformer input-channel="singleoutcomeChannel" output-channel="jdbcChannel" method="transform">
            <beans:bean class="transformers.SingleoutcomeToMap" />
        </int:transformer>
    
        <int-jdbc:stored-proc-outbound-channel-adapter   
            data-source="dataSource" channel="jdbcChannel" stored-procedure-name="insert_outcome" 
            ignore-column-meta-data="true">
    
            <int-jdbc:sql-parameter-definitions ... />
    
            <int-jdbc:parameter ... />
    
        </int-jdbc:stored-proc-outbound-channel-adapter>
    
        <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" >
            <property name="driverClassName" value="org.postgresql.Driver"/>
            <property ... />
        </bean>
    
    </beans>
    

1 个答案:

答案 0 :(得分:1)

你认为正确的方法。如果您的PublishSubscribeChannel没有Executor,则每个下一个订阅者将在上一个完成其工作时等待。因此,在DB上完成所有操作之前,不会调用spllitter。默认情况下,当第一个订户无法处理消息(而不是数据库连接?)时,所有其他用户都不会被呼叫。

可以使用<request-handler-advice-chain>ExpressionEvaluatingRequestHandlerAdvice配置另一种实现类似行为的方式:https://docs.spring.io/spring-integration/docs/5.0.4.RELEASE/reference/html/messaging-endpoints-chapter.html#expression-advice

所有拆分器下游流并发和多线程已经与DB逻辑无关。在DB正确执行请求之前,并行性不会发生。