I'm using @MessagingGateway
in order to bridge between spring-mvc
@Controller
and spring-integration
. The @MessagingGateway
declaration looks like this:
package a.b.c;
import org.springframework.integration.annotation.*;
import org.springframework.stereotype.Component;
@MessagingGateway(name="inboundGateway" defaultRequestTimeout="2000"
defaultReplyTimeout="2000")
@Component
public interace InboundGateway {
@Gateway(requestChannel = "getSomething")
Message<SomeValue> getSomething(@Headers Map<String, Object> headers);
}
which is referenced from a Controller
@Controller
@RequestMapping("/some/base/path")
public class SomeController {
private final InboundGateway inboundGateway;
public SomeController(InboundGateway inboundGateway) {
this.inboundGateway = inboundGateway;
}
@GetMapping(value = "things", produces = { "application/json" })
public ResponseEntity<SomeValue> getSomething(RequestContext<String> requestContext) {
Message<SomeValue> response = inboundGateway.getSomething(requestContext);
....
}
I was thinking that the definitions of defaultRequestTimeout
and defaultReplyTimeout
would raise a timeout at the inboundGateway
if the response was not returned within the specified time.
However, I'm seeing instead that the time used within the method getSomething()
can surpass the specified time, in this example, 2 seconds. It seems that the 2 seconds is used as a timeout for the calls to downstream systems, but not as a timeout for the return from getSomething()
.
Am I understanding this correctly? Is there some simple, declarative way of managing the timeout at the inboundGateway
level? Any pointers appreciated.
The behavior you explaining is typical for flows where your inboundGateway
is a DirectChannel
. This way the message process is performed directly on the thread producing that message. So, it cannot reach the replyTimeout
for result since that thread is blocked waiting for message handling.
See more info in docs for different channels: https://docs.spring.io/spring-integration/reference/channel/implementations.html
Also see docs for those timeouts on the Gateway: https://docs.spring.io/spring-integration/reference/gateway.html
As a simple solution for your expectation you may consider to use a QueueChnanel
for that inboundGateway
or an ExecutorChannel
. This way the processing will be handed off to a different thread and gateway will be able easily move on to the reply waiting block. And that's where that replyTimeout
will have an effect.
It is also explained in that annotation attribute JavaDocs:
/**
* Provides the amount of time dispatcher would wait to send a {@code Message}. This
* timeout would only apply if there is a potential to block in the send call. For
* example if this gateway is hooked up to a {@code QueueChannel}. Value is specified
* in milliseconds; it can be a simple long value or a SpEL expression; array variable
* #args is available.
* See {@link Gateway#requestTimeout()} for per-method configuration.
* @return the suggested timeout in milliseconds, if any
*/
String defaultRequestTimeout() default IntegrationContextUtils.DEFAULT_TIMEOUT_STRING;