Reputation: 1086
I have a below setup with spring integration.
<int-http:inbound-gateway id="restListener"
request-channel="restChannel"
reply-channel="restResponseChannel"
path="/service"
supported-methods="POST"
reply-timeout="5000"
</int-http:inbound-gateway>
<int:channel id="restChannel"/>
<int:channel id="restResponseChannel"/>
<int:service-activator input-channel="restChannel"
ref="restRequestHandler"
method="handleRestRequest"/>
I receive 2 different types of POST requests on gateway and both of them are passed to service-activator
for processing. In one type of POST request my service-activator
can immediately process it and reply back with a standard response. However, other type of request will be routed through different channels and processed by different processors (depending on the content). I want the output for processing both type of requests to be sent as response
of REST call.
For first type of request I can simply do this
public void handleRestRequest(Message<JsonNode> postMessage) {
if (type1) {
// Do processing
restResponseChannel.send(MessageBuilder
.withPayload("{\"result\":\"success!\"}")
.copyHeaders(postMessage.getHeaders())
.build());
} else {
// send to another channel for further processing
}
}
But for second type of request if I try to send
my output to restResponseChannel
(without headers) then I get below exception
org.springframework.messaging.core.DestinationResolutionException: no output-channel or replyChannel header available
I do not have access to original headers for second type of request. How can I send the output to reply-channel
? (I read somewhere that gateway creates an anonymous channel to connect to the reply-channel
and not having those headers is causing the exception, however I don't understand the underlying mechanism completely to debug this myself)
Upvotes: 1
Views: 2148
Reputation: 121560
You understand that absolutely correctly.
If you don't carry request headers, there is no TemporaryReplyChannel
header to correlate reply with response. See GenericMessagingTemplate.doSendAndReceive()
for implementation:
TemporaryReplyChannel tempReplyChannel = new TemporaryReplyChannel(this.throwExceptionOnLateReply);
requestMessage = MessageBuilder.fromMessage(requestMessage).setReplyChannel(tempReplyChannel)
.setHeader(this.sendTimeoutHeader, null)
.setHeader(this.receiveTimeoutHeader, null)
.setErrorChannel(tempReplyChannel).build();
try {
doSend(channel, requestMessage, sendTimeout);
}
catch (RuntimeException ex) {
tempReplyChannel.setSendFailed(true);
throw ex;
}
Message<?> replyMessage = this.doReceive(tempReplyChannel, receiveTimeout);
So, if there is no that header, no possibility to accept reply. The behavior is the same like in many other messaging replyAddress
patterns.
That reply-channel="restResponseChannel"
is just for convenience when you don't want to consult header for the next channel or when you would like to send a reply not only to the response but to somewhere else - publish-subscribe pattern.
You don't have choice unless carry headers anyway. One case is to use Message
directly, another is with the @Headers Map<String, Object>
service method.
Upvotes: 2