级联聚合器不返回消息

时间:2014-01-21 17:44:14

标签: spring-integration

我正在使用spring集成从外部系统同时提取不同的帐户详细信息(使用taskmanager)并将其聚合到一个帐户对象中。为此,我将不得不对消息进行两级分割,并且在获取之后需要在两个级别进行聚合。我使用简单的pojos进行拆分器,路由器和聚合器实现。我正在实施关联策略并使用简单的消息组,但没有实现任何发布策略。出于某种原因,我的消息在第二个聚合器中丢失了。当我调试时,我可以看到来自第一级聚合器的消息传递到第二级聚合器,但它无法将这些消息传递到输出通道。

还有一个观察结果是,如果只有一条消息,我会得到输出。但是在导致多个消息聚合的任何条件中,我都没有看到任何输出并且线程被挂起。

任何帮助表示赞赏!!

以下是上下文定义。

    <bean id="accountManager" class="<package>.AccountManager"/>

<int:gateway id="accountBuilder"
    service-interface="<package>.AccountBuilder" default-request-channel="accountRequest"  default-reply-channel="allAccounts"/>

<int:channel id="accountRequest"/>
<int:channel id="allAccounts"/>
<int:splitter input-channel="accountRequest" output-channel="accountRequests" ref="accountSplitter" method="split"/>

<int:channel id="accountRequests">
    <int:dispatcher task-executor="accountServiceTaskExecutor"/>
</int:channel>

<int:router input-channel="accountRequests" ref="accountRouter" method="routeAccountRequests">
    <int:mapping channel="retailRequest"/>
    <int:mapping channel="manualRequest"/>
</int:router>

<bean id="accountMessageStore" class="org.springframework.integration.store.SimpleMessageStore" />

<bean id="searchResultMessageStoreReaper" class="org.springframework.integration.store.MessageGroupStoreReaper">
    <property name="messageGroupStore" ref="accountMessageStore" />
    <property name="timeout" value="2000" />
</bean>

<!-- **************************************************************************** -->
<!-- **************************** RETAIL ACCOUNTS ******************************* -->
<!-- **************************************************************************** -->

<int:channel id="retailRequest"/>

<int:splitter input-channel="retailRequest" output-channel="retailAccountRequests" ref="retailAccountSplitter" method="split"/>

<int:channel id="retailAccountRequests">
    <int:dispatcher task-executor="accountServiceTaskExecutor"/>
</int:channel>

<int:router input-channel="retailAccountRequests" ref="retailAccountRouter" method="routeRetailAccountRequests">
    <int:mapping channel="retailAccountDataRequest"/>
    <int:mapping channel="retailAccountDetailsRequest"/>
    <int:mapping channel="retailAccountPositionsRequest"/>
</int:router>

<int:channel id="retailAccountDataRequest"/>
<int:service-activator input-channel="retailAccountDataRequest" ref="retailAccountDataMapper"
                       method="getRetailAccountData" output-channel="aggregatedRetailAccounts"/>

<int:channel id="retailAccountDetailsRequest"/>
<int:service-activator input-channel="retailAccountDetailsRequest" ref="retailAccountDetailsMapper"
                       method="getRetailAccountDetails" output-channel="aggregatedRetailAccounts"/>

<int:channel id="retailAccountPositionsRequest"/>
<int:service-activator input-channel="retailAccountPositionsRequest" ref="retailAccountPositionsMapper"
                       method="getRetailAccountPositions" output-channel="aggregatedRetailAccounts"/>

<int:channel id="aggregatedRetailAccounts" />
<int:aggregator input-channel="aggregatedRetailAccounts"
    ref="retailAccountAggregator" method="aggregate" output-channel="aggregatedAccounts"
    message-store="accountMessageStore" expire-groups-upon-completion="true"/>

<!-- ************************** END RETAIL ACCOUNTS ***************************** -->

<!-- **************************************************************************** -->
<!-- **************************** MANUAL ACCOUNTS ******************************* -->
<!-- **************************************************************************** -->

<int:channel id="manualRequest"/>

<int:splitter input-channel="manualRequest" output-channel="manualAccountRequests" ref="manualAccountSplitter" method="split"/>

<int:channel id="manualAccountRequests">
    <int:dispatcher task-executor="accountServiceTaskExecutor"/>
</int:channel>

<int:router input-channel="manualAccountRequests" ref="manualAccountRouter" method="routeManualAccountRequests">
    <int:mapping channel="manualAccountDataRequest"/>
    <int:mapping channel="manualAccountDetailsRequest"/>
    <int:mapping channel="manualAccountPositionsRequest"/>
</int:router>

<int:channel id="manualAccountDataRequest"/>
<int:service-activator input-channel="manualAccountDataRequest" ref="manualAccountDataMapper"
                       method="getManualAccountData" output-channel="aggregatedManualAccounts"/>

<int:channel id="manualAccountDetailsRequest"/>
<int:service-activator input-channel="manualAccountDetailsRequest" ref="manualAccountDetailsMapper"
                       method="getManualAccountDetails" output-channel="aggregatedManualAccounts"/>

<int:channel id="manualAccountPositionsRequest"/>
<int:service-activator input-channel="manualAccountPositionsRequest" ref="manualAccountPositionsMapper"
                       method="getManualAccountPositions" output-channel="aggregatedManualAccounts"/>

<int:channel id="aggregatedManualAccounts"/>
<int:aggregator input-channel="aggregatedManualAccounts"
ref="manualAccountAggregator" method="aggregate" output-channel="aggregatedAccounts"
message-store="accountMessageStore" expire-groups-upon-completion="true"/>

<!-- ************************** END MANUAL ACCOUNTS ***************************** -->

<int:channel id="aggregatedAccounts" />
<int:aggregator input-channel="aggregatedAccounts" ref="accountAggregator"
    method="aggregate" output-channel="allAccounts" message-store="accountMessageStore"
    expire-groups-upon-completion="true" />




<bean id="accountServiceTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="25" />
    <property name="maxPoolSize" value="250" />
    <property name="queueCapacity" value="500" />
</bean>

1 个答案:

答案 0 :(得分:1)

使用标准相关标头(correlationId)时,框架会在堆栈中自动维护嵌套序列详细信息(correlationIdsequenceSizesequenceNumber)被推送(在后续拆分器中)并在标题sequenceDetails下弹出(在聚合器中)。请参阅下面的MessageBuilder.pushSequenceDetails()和相应的popSequenceDetails()

如果您使用的是非标准关联,那么在嵌套拆分器时,您有责任以类似的方式保持它。

非标准关联不是问题,只要您将数据存储在correlationId标头中,如果您希望框架处理嵌套拆分。

与往常一样,DEBUG通过流记录和跟踪消息通常会识别这些类型的问题。

PS:始终尝试指出您正在使用的版本。