简体   繁体   中英

Intercept a Spring integration http:inbound-gateway's replyChannel

I would like to apply an Interceptor on the reply-channel of an http:inbound-gateway to save some event related data to a table. The flow continues in a chain which then goes to a header-value-router . As an example let's take a service-activator at the end of this flow, where the output-channel is not specified. In this case, the replyChannel header holds a TemporaryReplyChannel object (anonymous reply channel) instead of the gateway's reply-channel . This way the Interceptor is never called.

Is there a way to "force" the usage of the specified reply-channel? The Spring document states that

by defining a default-reply-channel you can point to a channel of your choosing, which in this case would be a publish-subscribe-channel. The Gateway would create a bridge from it to the temporary, anonymous reply channel that is stored in the header.

I've tried using a publish-subscribe-channel as reply-channel , but it didn't make any difference. Maybe I misunderstood the article...

Inside my chain I've also experimented with a header-enricher . I wanted to overwrite the value of the replyChannel with the id of the channel I want to intercept (submit.reply.channel). While debugging I was able to see "submit.reply.channel" in the header, but then I got an exception java.lang.NoClassDefFoundError: org/springframework/transaction/interceptor/NoRollbackRuleAttribute and stopped trying ;-)

Code snippets

<int-http:inbound-gateway id="submitHttpGateway"
    request-channel="submit.request.channel" reply-channel="submit.reply.channel" path="/submit" supported-methods="GET">
    <int-http:header name="requestAttributes" expression="#requestAttributes" />
    <int-http:header name="requestParametersMap" expression="#requestParams" />
</int-http:inbound-gateway>

<int:channel id="submit.request.channel" />
<int:publish-subscribe-channel id="submit.reply.channel">
    <int:interceptors>
        <int:ref bean="replyChannelInterceptor" />
    </int:interceptors>
</int:publish-subscribe-channel>

Thanks in advance for your help!

The only "easy" way is to explicitly send the reply via the output-channel on the last endpoint.

In fact, all that happens when you send to a declared channel is the reply channel is simply bridged to the replyChannel header.

You could do it by saving off the replyChannel header in another header, set the replyChannel header to some other channel (which you can intercept); then restore the replyChannel header to the saved-off channel before the reply is returned to the gateway.

EDIT:

Sample config...

<int:channel id="in" />

<int:header-enricher input-channel="in" output-channel="next">
    <int:header name="origReplyChannel" expression="headers['replyChannel']"/>
    <int:reply-channel ref="myReplies" overwrite="true" />
</int:header-enricher>

<int:router input-channel="next" expression="payload.equals('foo')">
    <int:mapping value="true" channel="channel1" />
    <int:mapping value="false" channel="channel2" />
</int:router>

<int:transformer input-channel="channel1" expression="payload.toUpperCase()" />

<int:transformer input-channel="channel2" expression="payload + payload" />

<int:channel id="myReplies" />

<!-- restore the reply channel -->
<int:header-enricher input-channel="myReplies" output-channel="tapped">
    <int:reply-channel expression="headers['origReplyChannel']" overwrite="true" />
</int:header-enricher>

<int:channel id="tapped">
    <int:interceptors>
        <int:wire-tap channel="loggingChannel" />
    </int:interceptors>
</int:channel>

<int:logging-channel-adapter id="loggingChannel" log-full-message="true" logger-name="tapInbound"
    level="INFO" />

<!-- route reply -->
<int:bridge id="bridgeToNowhere" input-channel="tapped" />

Test:

MessageChannel channel = context.getBean("in", MessageChannel.class);
MessagingTemplate template = new MessagingTemplate(channel);
String reply = template.convertSendAndReceive("foo", String.class);
System.out.println(reply);
reply = template.convertSendAndReceive("bar", String.class);
System.out.println(reply);  }

Result:

09:36:30.224 INFO  [main][tapInbound] GenericMessage [payload=FOO, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@fba92d3, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@fba92d3, id=326a610f-80c6-5b74-0158-e3644b732aab, origReplyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@fba92d3, timestamp=1442496990223}]
FOO
09:36:30.227 INFO  [main][tapInbound] GenericMessage [payload=barbar, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@662b4c69, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@662b4c69, id=d161917c-ca73-a5a9-d0f1-d7a4346a459e, origReplyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@662b4c69, timestamp=1442496990227}]
barbar

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM