我正在使用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>
答案 0 :(得分:1)
使用标准相关标头(correlationId
)时,框架会在堆栈中自动维护嵌套序列详细信息(correlationId
,sequenceSize
,sequenceNumber
)被推送(在后续拆分器中)并在标题sequenceDetails
下弹出(在聚合器中)。请参阅下面的MessageBuilder.pushSequenceDetails()和相应的popSequenceDetails()
。
如果您使用的是非标准关联,那么在嵌套拆分器时,您有责任以类似的方式保持它。
非标准关联不是问题,只要您将数据存储在correlationId
标头中,如果您希望框架处理嵌套拆分。
与往常一样,DEBUG通过流记录和跟踪消息通常会识别这些类型的问题。
PS:始终尝试指出您正在使用的版本。