2
votes

I do not know if I'm following this issue correctly - I send a PUT request via RestTemplate as below:

restTemplate.exchange(getBaseUrl() + "/api/getVoid", HttpMethod.PUT, new HttpEntity<String>("someMessage"), Void.class);

or:

restTemplate.put(getBaseUrl() + "/api/getVoid", "someMessage");

PUT so it means I do not expect a reply content. My HTTP PUT service is exposed by Spring Integration components:

<int-http:inbound-gateway supported-methods="PUT" reply-timeout="5000"
                      path="/api/getVoid"
                      request-channel="some-request-channel1" reply-channel="some-reply-channel1">

<int:channel id="some-request-channel1"/>
<int:channel id="some-reply-channel1"/>

<int:service-activator input-channel="some-request-channel1" output-channel="some-reply-channel1" ref="someService"
                   method="restMethodVoid"/>

I have a reply channel on my inbound-gateway set but the service that processes the request "returns" void (some PUT operation).

@ServiceActivator
public void restMethodVoid(Message<String> request) {
   log.info("DONE! But you will get 500");
}

And now the issue - I can see that sending a PUT request into inbound-gateway to be process with void returning method throws 500 Internal Server Error on reply timeout.

Does it mean there is not possibility to send PUT or any other request to SI http inbount gateway "operated by" void service methods?

This is the behaviour in 1.3.2 version but it behaves differently in 1.2.3 for example - the gateway behaviour seems to be the same - it times out but without throwing 500 - just gets back to still waiting request thread and releases it "nicely" (still just on timeout).

I do not see either behaviour perfect, but 1.3.2 is worse because let say I send PUT (or POST with Void.class as return type...) to be processes and it was processed fine - some critical transactional operations were committed and so on - method returned perfectly fine with void but caller gets 500. So this 500 is being propagated this to its caller... ending probably with an error on UI (which can really scare users;)). But everything went fine.

In the 1.2.3 behaviour - even with timeout but the thread could get back to its caller with 200 status, so propagate proper response code next.

Gary, Artem - can you please advice here?

1
This is the response from 1.2.3.RELEASE version: 11:16:01.882 [Thread-3] DEBUG o.s.web.client.RestTemplate - PUT request for "http://localhost:64526/api/getVoid" resulted in 200 (OK) (Still it was timeout). And from 1.3.2.RELEASE: org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error. Hmmmm52509791
I am not sure what you are referring to wither versions 1.2.3 and 1.3.2; those versions don't exist; the behavior was changed (fixed) in version 4.2 - see my answer below.Gary Russell
Sorry, I'm referring to Spring Boot release.m52509791

1 Answers

2
votes

See the discussion on this pull request.

When the downstream flow returns void you should use an inbound channel adapter, not a gateway; that fix was to correct a problem with the gateway when a timeout occurred - it was incorrectly returning 200, it now returns 500 (by default).

When using a gateway this way, you are incorrectly tying up a web container thread for the default timeout (1s) waiting for a reply that will never be received.

Repeating my full answer from there...

Gateways are for two-way interaction (request/reply); this fix corrected a problem where, if a timeout occurred, 200 OK was returned; which was incorrect.

You should use an <http:inbound-channel-adapter/> if you never expect a reply (such as in your case). Channel adapters are used for one-way interactions with the message flow (although in this case, a 200 OK is sent to the caller). One-way in this context means the flow doesn't return a reply.

In fact, this fix has simply exposed a bug in your configuration; before this change, the thread would be suspended for 1 second (the default reply-timeout) after the flow completes (waiting for a reply). This means that all your requests take 1 second longer than needed.

The adapter doesn't wait for a reply.