HTTP Interfaces are great but it's impossible to replace pure RestClient calls in all cases. For instance, code like
restClient.put()
.uri(...)
.body(body -> {
//use body as OutputStream
})
.retrieve()
.toBodilessEntity();
or
restClient.get()
.uri(...)
.exchange((req, resp) -> {
var inputStream = resp.getBody());
//use inputStream
});
cannot be replaced with HTTP Interface (as I know).
It causes minor inconvenience as HTTP Interface is used in 99% cases but RestClient is still injected to cover cases like download/upload large files without significant memory consumption and all other cases where Stream processing is needed.
Propose to add:
* OutputStream (or StreamingHttpOutputMessage.Body) as supported method parameter here https://docs.spring.io/spring-framework/reference/integration/rest-clients.html#rest-http-interface-method-parameters
* InputStream or (ResponseEntity
Comment From: ooraini
I'm in a similar situation. I tried using the ResponseEntity<InputStreamResource>
as response type with no luck(stream closed). It seems that the DefaultRestClient
unconditionally closes the ClientHttpResponse
in twr.
Comment From: kap199297
Is there any update on supporting InputStream? I tried with Resource and InputStream but no luck. We are planning to migrate to the HTTP interface, is there any other alternative to support file download?
Comment From: rstoyanchev
On closer look, HTTP Interfaces are meant to be a neutral contract between client and server, but support for StreamingHttpOutputMessage.Body
and InputStream
is client side only.
This is just a design guideline (not a hard rule), and StreamingHttpOutputStream.Body
is easy enough to adapt onto a call on RestClient
without any contract changes. However, InputStream
is more of a challenge. The common pattern is to call exchange
and consume the body within the callback. Support for this would require updates to the HttpExchangeAdapter
contract to support use of ExchangeFunction
, which would be RestClient specific, and client side only.
This makes me take a step back to reconsider the approach. Rather than adding support to write to OutputStream
and expect calling code to deal with the writing externally, wouldn't it make sense for this case to create an actual implementation class that works with RestClient
encapsulates the details of writing to the OutputStream
, and likewise for the InputStream on the response side?
Comment From: hostmenow
To me, the whole point of HTTP interfaces is to not deal with RestClient. It would be great to keep it as a single, clean interface and support streaming.
wouldn't it make sense for this case to create an actual implementation class that works with RestClient
It makes sense but it breaks the convenience of using HTTP interfaces. Just for one endpoint, we need to return to the old approach.
Comment From: rstoyanchev
I found a way to do this from within RestClientAdapter
without changing any contracts.