使用Splitter重用几个网关方法的service-activator

时间:2016-03-23 17:15:17

标签: spring-integration

是否有人碰巧知道重用服务激活器是否有效,以及使用多种方法(入站)的输出通道,尤其是分路器和聚合器。

- >总是在网关上有结果。

在几个测试中似乎工作正常。一旦我添加了一个带有聚合器的拆分器,我就会将错误结果路由到网关,然后网关失败并出现转换异常(在我的例子中,它不能将布尔值转换为整数)。

谢谢,

流量

Spring Integration Flow

Spring Integration Config

    <?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"
    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">

    <int:gateway service-interface="activity.BulbMessageGateway">
        <int:method name="sendToBulb" request-channel="bulbMessages" reply-channel="bulbSendResult"></int:method>
        <int:method name="updateHomeLightStatus" request-channel="homeBulbEntity" reply-channel="homeBulbEntityResult">
        </int:method>
        <int:method name="updateLightStatus" request-channel="bulbEntities" reply-channel="bulbSendResult">
            <int:header name="homeId" expression="#args[0].homeId"/>
            <int:header name="bulbId" expression="#args[0].strongId"/>
        </int:method>
    </int:gateway>

    <int:channel id="bulbMessages" />
    <int:channel id="bulbSendResult" />
    <int:channel id="bulbEntities" />

    <int:channel id="homeBulbEntity" />
    <int:channel id="homeBulbEntityResult" />

    <int:chain input-channel="homeBulbEntity" output-channel="bulbEntities">
        <int:splitter expression="payload.bulbs" />
        <int:header-enricher>
            <int:header name="bulbId" expression="payload.strongId"/>
            <int:header name="homeId" expression="payload.homeId"/>
        </int:header-enricher>
    </int:chain>

    <int:transformer method="bulbToLightStatus" input-channel="bulbEntities" output-channel="bulbMessages">
        <bean class="util.BulbTransformer"></bean>
    </int:transformer>

    <int:aggregator input-channel="bulbSendResult" output-channel="homeBulbEntityResult" method="aggregate">
        <bean class="util.BooleanAggregator" />
    </int:aggregator>

    <int:service-activator input-channel="bulbMessages" output-channel="bulbSendResult" method="send">
        <bean class="activity.BulbWebsocketMessageSenderBA" />
    </int:service-activator>
</beans>

单元测试

@Test
public void sendMessageNoReceiver() {
    assertFalse(gateway.sendToBulb(new HomeId("1"), new BulbId("1"), BulbMessageBuilder.restart("foo")));
}

@Test
public void sendMessageWithReceiver() {
    MockSession<BulbId, BulbBE> bulbSession = new MockSession<BulbId, BulbBE>(new BulbBE(HomeId.of("1"), BulbId.of("1"), "bulb", "pass"));
    registry.addBulbSession(bulbSession);
    assertTrue(gateway.sendToBulb(new HomeId("1"), new BulbId("1"), BulbMessageBuilder.restart("foo")));
    assertEquals(1, bulbSession.receivedMessages());
}

@Test
public void updateBulbStatus() {
    final MockSession<BulbId, BulbBE> bulbSession1 = new MockSession<BulbId, BulbBE>(new BulbBE(HomeId.of("1"), BulbId.of("1"), "bulb", "pass"));
    assertFalse(gateway.updateLightStatus(bulbSession1.getIdentity()));

    registry.addBulbSession(bulbSession1);
    assertTrue(gateway.updateLightStatus(bulbSession1.getIdentity()));
    assertEquals(1, bulbSession1.receivedMessages());

    final MockSession<BulbId, BulbBE> bulbSession2 = new MockSession<BulbId, BulbBE>(new BulbBE(HomeId.of("1"), BulbId.of("2"), "bulb", "pass"));
    assertFalse(gateway.updateLightStatus(bulbSession2.getIdentity()));

    registry.addBulbSession(bulbSession2);
    assertTrue(gateway.updateLightStatus(bulbSession2.getIdentity()));
    assertTrue(gateway.updateLightStatus(bulbSession2.getIdentity()));

    assertEquals(2, bulbSession2.receivedMessages());
    assertEquals(1, bulbSession1.receivedMessages());
}
@Test
public void updateHomeBulbStatus() {
    final HomeBE home = new HomeBE();
    home.setId(new ObjectId());

    final MockSession<BulbId, BulbBE> bulbSession1 = new MockSession<BulbId, BulbBE>(new BulbBE(home.getStrongId(), BulbId.of("1"), "bulb", "pass"));
    registry.addBulbSession(bulbSession1);
    final MockSession<BulbId, BulbBE> bulbSession2 = new MockSession<BulbId, BulbBE>(new BulbBE(home.getStrongId(), BulbId.of("2"), "bulb", "pass"));
    registry.addBulbSession(bulbSession2);

    home.addBulb(bulbSession1.getIdentity());

    assertEquals(1, gateway.updateHomeLightStatus(home));
    assertEquals(1, bulbSession1.receivedMessages());
    assertEquals(0, bulbSession2.receivedMessages());

    home.addBulb(bulbSession2.getIdentity());
    assertEquals(2, gateway.updateHomeLightStatus(home));
    assertEquals(2, bulbSession1.receivedMessages());
    assertEquals(1, bulbSession2.receivedMessages());
}

如果与其他测试一起执行,则最后一次测试失败。如果单独执行它就会通过。

错误是最后一个方法(使用拆分器)现在接收一个布尔值,这似乎是其他两个方法注册的结果。这些方法的结果是布尔值。

1 个答案:

答案 0 :(得分:1)

请分享关于此事的配置。

根据您的图表,如果您尽可能地最小化配置以隔离问题会更好。

另一方面,请更具体一点:你的问题完全不清楚。

这是您自己的服务。我们怎样才能确定在不同的地方使用它是否安全?只有你作为作者才能确定这一点。

<强>更新

抱歉延误。忙着发布。

感谢分享您的用例配置。

现在我看到了问题。

您可以在网关的方法a reply-channel上随处使用。如果需要,请参阅documentation

  

通常,您不必指定默认回复频道,因为网关会自动创建一个临时的匿名回复频道,用于监听回复。但是,在某些情况下可能会提示您定义默认回复通道(或带有适配器网关的回复通道,如HTTP,JMS等)。

由于您在不同的地方使用相同的bulbSendResult,因此行为确实无法预测。无论该频道是DirectChannel,所以round-robin平衡器都在现场。

你应该完全摆脱那些reply-channel,只需依靠replyChannel标题上的下游组件。因此,您应该删除组件中用于返回对网关的回复的output-channel

例如,上一个service-activator应该是这样的:

<int:service-activator input-channel="bulbMessages" method="send">
    <bean class="activity.BulbWebsocketMessageSenderBA"/>
</int:service-activator>

由于您一般会质疑如何重复使用此service-activator,我会回答您的配置问题:

<int:chain input-channel="homeBulbEntity">
    <int:splitter expression="payload.bulbs"/>
    <int:header-enricher>
        <int:header name="bulbId" expression="payload.strongId"/>
        <int:header name="homeId" expression="payload.homeId"/>
    </int:header-enricher>
    <int:transformer method="bulbToLightStatus">
        <bean class="util.BulbTransformer"/>
    </int:transformer>
    <int:gateway request-channel="bulbMessages"/>
    <int:aggregator method="aggregate">
        <bean class="util.BooleanAggregator"/>
    </int:aggregator>
</int:chain>

注意output-channel缺席的<chain>。因此,它会直接从标头replyChannel发送回复,并以return方式向您的updateHomeLightStatus网关方法发送回复。

另一个技巧是<int:gateway request-channel="bulbMessages"/><chain>流中间的消息发送到您的<service-activator>并等待来自那里的回复与顶级网关完全相同 - 通过replyChannel标题。对于没有<service-activator>的{​​{1}},它是一个黑框,用于发送回复。它只使用标题中的output-channel

收到replyChannel中的回复gateway后,将邮件推送到<chain>

<aggregator>执行其逻辑时,结果将作为aggregator的输出发送到顶级网关。

这就是全部。

让我知道还有什么不清楚。