The Flow based BodyProcessor API is still difficult to use.
The existing convenience implementations of HttpResponse.BodyProcessor
don’t support streaming: they load the entire response body and only then
make the data available to the application. This approach optimises for
throughput in some applications but at the cost of latency and memory use.
Many applications will want to make different trade-offs:
- For example, an application that loads an image may want to stop loading
the image if the image header indicates that the image is too large or an
unsupported format; or it may want to transcode the image as it is received
(e.g. into a compressed texture format for the GPU). The current
implementations make this hard.
⇨ see ExampleUseCases.downloadImage() , which is incomplete draft
code involving a pseudo / imagined Image format.
- Some environments are more constrained by memory than throughput.
Suggestions:
- Ensure that a blocking (e.g. InputStream based) pull-based convenience API
is possible to write on top of HttpResponse.BodyProcessor. Pull-based APIs
are much easier to use because application state is on the call stack (instead
of instance fields), there is no callback lifecycle to understand, and stack traces
start in application code. It doesn’t necessarily have to be part of the initial
release of the API, but it should be possible to implement such a simpler API
in a reasonably efficient manner.
⇨ PipedResponseStream.java is a sample implementation of such a blocking
convenience API on top of the current HTTP Client API. It implements a
BodyProcessor that makes its contents available via an InputStream as it
arrives, decoupled via an internal buffer (currently sized in # of ByteBuffers rather
than # bytes, because of the above limitation). This file is the most polished / least
draft/experimental part of the supplied example code.
- RequestBody.BodyProcessor can probably also be exposed as a simpler API,
but we haven’t investigated this in as much detail.
⇨ RequestBodyProcessors.copy() is some convenience code to copy the bytes
out of a RequestBody.BodyProcessor. Applications might be interested in such
convenience methods.
This issue has been filed to capture comments raised by tobiast at google dot com, see
http://mail.openjdk.java.net/pipermail/net-dev/2017-July/010872.html
The existing convenience implementations of HttpResponse.BodyProcessor
don’t support streaming: they load the entire response body and only then
make the data available to the application. This approach optimises for
throughput in some applications but at the cost of latency and memory use.
Many applications will want to make different trade-offs:
- For example, an application that loads an image may want to stop loading
the image if the image header indicates that the image is too large or an
unsupported format; or it may want to transcode the image as it is received
(e.g. into a compressed texture format for the GPU). The current
implementations make this hard.
⇨ see ExampleUseCases.downloadImage() , which is incomplete draft
code involving a pseudo / imagined Image format.
- Some environments are more constrained by memory than throughput.
Suggestions:
- Ensure that a blocking (e.g. InputStream based) pull-based convenience API
is possible to write on top of HttpResponse.BodyProcessor. Pull-based APIs
are much easier to use because application state is on the call stack (instead
of instance fields), there is no callback lifecycle to understand, and stack traces
start in application code. It doesn’t necessarily have to be part of the initial
release of the API, but it should be possible to implement such a simpler API
in a reasonably efficient manner.
⇨ PipedResponseStream.java is a sample implementation of such a blocking
convenience API on top of the current HTTP Client API. It implements a
BodyProcessor that makes its contents available via an InputStream as it
arrives, decoupled via an internal buffer (currently sized in # of ByteBuffers rather
than # bytes, because of the above limitation). This file is the most polished / least
draft/experimental part of the supplied example code.
- RequestBody.BodyProcessor can probably also be exposed as a simpler API,
but we haven’t investigated this in as much detail.
⇨ RequestBodyProcessors.copy() is some convenience code to copy the bytes
out of a RequestBody.BodyProcessor. Applications might be interested in such
convenience methods.
This issue has been filed to capture comments raised by tobiast at google dot com, see
http://mail.openjdk.java.net/pipermail/net-dev/2017-July/010872.html