I am using URL class to read an InputStream from it. Is there any way I can use RestTemplate for this?
InputStream input = new URL(url).openStream(); JsonReader reader = new JsonReader(new InputStreamReader(input, StandardCharsets.UTF_8.displayName()));
How can I get InputStream
with RestTemplate
instead of using URL
?
That Resource class encapsulates a InputStream , which you can obtain via someResource. getInputStream() . Putting this all together, you can actually get an InputStream via RestTemplate out-of-the-box by specifying Resource. class as your RestTemplate invocation's response type.
RestTemplate provides a synchronous way of consuming Rest services, which means it will block the thread until it receives a response. RestTemplate is deprecated since Spring 5 which means it's not really that future proof.
The getForObject method fetches the data for the given response type from the given URI or URL template using HTTP GET method. To fetch data for the given key properties from URL template we can pass Object Varargs and Map to getForObject method. The getForObject returns directly the object of given response type.
Conclusion RestTemplate uses Java Servlet API and is therefore synchronous and blocking. Conversely, WebClient is asynchronous and will not block the executing thread while waiting for the response to come back. The notification will be produced only when the response is ready. RestTemplate will still be used.
The previous answers are not wrong, but they don't go into the depth that I like to see. There are cases when dealing with low level InputStream
is not only desirable, but necessary, the most common example being streaming a large file from source (some web server) to destination (a database). If you try to use a ByteArrayInputStream
, you will be, not so surprisingly, greeted with OutOfMemoryError
. Yes, you can roll your own HTTP client code, but you'll have to deal with erroneous response codes, response converters etc. If you are already using Spring, looking to RestTemplate
is a natural choice.
As of this writing, spring-web:5.0.2.RELEASE
has a ResourceHttpMessageConverter
that has a boolean supportsReadStreaming
, which if set, and the response type is InputStreamResource
, returns InputStreamResource
; otherwise it returns a ByteArrayResource
. So clearly, you're not the only one that asked for streaming support.
However, there is a problem: RestTemplate
closes the response soon after the HttpMessageConverter
runs. Thus, even if you asked for InputStreamResource
, and got it, it's no good, because the response stream has been closed. I think this is a design flaw that they overlooked; it should've been dependent on the response type. So unfortunately, for reading, you must consume the response fully; you can't pass it around if using RestTemplate
.
Writing is no problem though. If you want to stream an InputStream
, ResourceHttpMessageConverter
will do it for you. Under the hood, it uses org.springframework.util.StreamUtils
to write 4096 bytes at a time from the InputStream
to the OutputStream
.
Some of the HttpMessageConverter
support all media types, so depending on your requirement, you may have to remove the default ones from RestTemplate
, and set the ones you need, being mindful of their relative ordering.
Last but not the least, implementations of ClientHttpRequestFactory
has a boolean bufferRequestBody
that you can, and should, set to false
if you are uploading a large stream. Otherwise, you know, OutOfMemoryError
. As of this writing, SimpleClientHttpRequestFactory
(JDK client) and HttpComponentsClientHttpRequestFactory
(Apache HTTP client) support this feature, but not OkHttp3ClientHttpRequestFactory
. Again, design oversight.
Edit: Filed ticket SPR-16885.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With