I've run into failed replies when using the webflux gateway Java DSL in Spring Integration. It only works for the first few requests (<8 to be specific), I'm getting reply errors afterwards:
org.springframework.integration.MessageTimeoutException: failed to receive JMS response within timeout of: 5000ms
at org.springframework.integration.jms.JmsOutboundGateway.handleRequestMessage(JmsOutboundGateway.java:741) ~[spring-integration-jms-5.3.2.RELEASE.jar:5.3.2.RELEASE]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
When I use .fluxTransform(f -> f)
on the inbound gateway OR when I use the non-reactive http outbound gateway, I don't get the errors, even on a jmeter benchmark with thousands of requests.
- Why do I have to call
fluxTransform(f -> f)
in the first flow to make it work? - Why does it work without
fluxTransform(f -> f)
when I useHttp.outboundGateway
in the second flow?
Scenario
I've created a route using four gateways for a rather complex setup to make a web request on a remote machine, but I'm
Integration Flow 1:
inbound webflux gateway -> outbound jms gateway
@Bean
public IntegrationFlow step1() {
// request-reply pattern using the jms outbound gateway
var gateway = Jms.outboundGateway(jmsConnectionFactory)
.requestDestination("inboundWebfluxQueue")
.replyDestination("outboundWebfluxQueue")
.correlationKey("JMSCorrelationID");
// send a request to jms, wait for the reply and return message payload as response
return IntegrationFlows.from(webfluxServer("/example/webflux"))
// won't work consistently without the next line
.fluxTransform(f -> f)
.handle(gateway).get();
}
Integration Flow 2:
inbound jms gateway -> outbound webflux gateway
@Bean
public IntegrationFlow step2_using_webflux() {
var gateway = WebFlux.outboundGateway("http://localhost:8080/actuator/health")
.httpMethod(HttpMethod.GET)
.expectedResponseType(String.class)
// ignore headers
.mappedResponseHeaders();
return IntegrationFlows.from(jmsInboundGateway())
// use webflux outbound gateway to send the request to the TEST_URL
.handle(gateway).get();
}
The complete route looks like this:
client web request -> flow 1 -> (message broker) -> flow 2 -> server web request