【问题标题】:Spring Integration - Inbound file endpoint. How to process a file correctly.Spring Integration - 入站文件端点。如何正确处理文件。
【发布时间】:2016-03-03 14:37:21
【问题描述】:

我有一个如下的 Spring 集成流程。

<int-file:inbound-channel-adapter id="filesIn"
        directory="file:${incomingDir}" 
        filename-pattern="*.txt" 
        prevent-duplicates="true">
    <int:poller id="poller" fixed-delay="5000"/>
    </int-file:inbound-channel-adapter>

    <int:splitter input-channel="filesIn" 
        ref="filesSplitterService"
        method="splitFilesToReportContent"
        output-channel="reportProcessIn"
     />

     <int:channel id="reportProcessIn"/>

     <int:chain input-channel="reportProcessIn" output-channel="reportProcessOut">    
        <int:service-activator ref="reportProcessorService" method="readReportMetaData" />
        <int:service-activator ref="reportProcessorService" method="saveReportFileInFileSystem" />
        <int:service-activator ref="reportProcessorService" method="saveReportMetaDataInDB" />
    </int:chain>

     <int:channel id="reportProcessOut"/>


    <bean id="filesSplitterService" class="com.app.integration.FilesSplitter"/>

    <bean id="reportProcessorService" class="com.app.reporting.integration.ReportProcessor"/>

传入的文件被一个服务分割并形成一个ReportContent列表。

然后服务链获取 ReportContent 的每个元素并处理它们以从文件内容中读取_report_meta_data(如报告ID,报告类型),将报告内容字符串保存到相应目录中的文件中,并将报表元数据保存在数据库中。流程运行良好,但似乎有一个松散的结局。

我得到以下异常。

org.springframework.integration.MessageDeliveryException: Dispatcher 没有订阅者

  1. 我不需要聚合拆分的元素。就我而言,在将元数据保存在数据库中之后,流程就完成了。

  2. 但是,我想在使用原始文件(我拆分为报告文件的主文件)后将其移动到其他目录。我怎样才能融入这种逻辑? File:outbound-channel 似乎是这样做的方式,但我不明白如何。

  3. 有没有办法避免基于 readReportMetaData 操作中读取的一些元数据的 saveReportFileInSystem 和 saveReportMetaDataInDB 操作。

为方便起见,我在下面给出了我的服务类的结构。

类:FileSplitter

public List<ReportContent> splitFilesToReportContent(File file){
} 

类:报告处理器

public ReportContent readReportMetaData(ReportContent reportContent) {


}



public ReportContent saveReportFileInFileSystem(ReportContent reportContent) {


    }

public ReportContent saveReportMetaDataInDB(ReportContent reportContent) {


    }

需要注意的一点是,我没有使用邮件标头。我还没有觉得有必要使用,但我可以使用。我是 Spring 集成的新手,所以任何改进此流程的建议都会有所帮助。

【问题讨论】:

    标签: java spring file integration spring-integration


    【解决方案1】:

    1.我得到以下异常... org.springframework.integration.MessageDeliveryException

    我想你在这里错过了file:outbound-channel-adapter 的定义。

    2。但是,我想在使用它后将原始文件(我拆分为报告文件的主文件)移动到其他目录。我怎样才能融入这种逻辑?

    正如14.3.4 File Outbound Channel Adapter 中所写,您应该为outbound-channel-adapter 使用delete-source-files 属性但是(!)

    ...仅当入站消息具有文件负载或 FileHeaders.ORIGINAL_FILE 标头值包含源文件实例或表示原始文件路径的字符串时,属性才会生效。

    所以,在您reportProcessorService 中,无论如何您都应该处理原始消息。您不再将源文件作为有效负载。因此,只有一种选择是正确设置FileHeaders.ORIGINAL_FILE 标头值。

    3.有没有办法避免基于 readReportMetaData 操作中读取的一些元数据的 saveReportFileInSystem 和 saveReportMetaDataInDB 操作?

    是的,有。在链 EIP 中 readReportMetaData 之后使用 PayloadTypeRouter (如果可能的话,因为它很简单)或 Configuring (Generic) Router

    【讨论】:

      【解决方案2】:

      SubscribableChannel(如您的reportProcessOut)确实没有订阅者或订阅者已停止时,我们通常有Dispatcher has no subscribers,这也可以视为“没有订阅者”。

      如果您对该结果不感兴趣,我们通常建议将&lt;service-activator&gt; 结果发送到nullChannel。仅使用标准的单向组件(&lt;outbound-channel-adapter&gt;)无法完成任务时就是这种情况。

      但是我想移动原始文件,我拆分成报告文件的主文件,

      您可以将&lt;publish-subscriber-channel&gt; 的第二个单向订阅者作为filesIn 来实现。以及具有标准File.renameTo() 功能的实现者。我没有理由用&lt;int-file:outbound-channel-adapter&gt; 之类的东西让你大吃一惊。您已经在文件系统上。因此,只需使用它的功能。当我们处理 FTP、SFTP 等远程文件时,我们需要文件适配器。

      您可以使用 Map&lt;String, Object&gt; headers 作为 3service 方法的第二个参数,Framework 将从请求 Message&lt;?&gt; 中为您注入适当的对象。

      请参阅 @Andriy Kryvtsun 关于“避免 saveReportFileInSystem”的回答。

      作为替代方案,您可以使用&lt;filter&gt; 跳过和丢弃因某种原因不应保存的消息。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-17
      • 2014-10-08
      • 1970-01-01
      • 2023-03-12
      • 2013-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多