Details
-
Improvement
-
Status: Resolved
-
Minor
-
Resolution: Fixed
-
None
-
None
Description
I intend to write structured data to a resource accessed via HttpClient. APIs for doing this (for JSON, YAML, XML) tend to make me pass an OutputStream which they will write to - they don't give me an InputStream.
HttpEntityEnclosingRequestBase (over in HttpClient) forces me to set an HttpEntity to get any data to the server.
HttpEntity seemingly forces me to implement getContent(), returning an InputStream.
I don't have an InputStream, so I am forced to choose between two workarounds:
A) Serialise all the data into an in-memory byte array and then stream it all back out again. I don't want to do this, because usually, the serialised form of the data takes up a lot more memory than the data itself, and in some cases we don't even have it in memory in the first place, so this would be asking for trouble.
B) Create a Pipe. Spin up a second thread to write the object to the OutputStream end of the pipe. Return the InputStream end. This can't actually be done because HttpEntity has no idea when the data stream is no longer needed. HttpClient doesn't own the InputStream so it can't close it. This means I can't even put the workaround in my implementation of HttpEntity - I have to put it in every location where I call the HttpClient and want to pass an entity.
After asking about it on StackOverflow, it turns out there is a third workaround. Just don't implement the method!
I think that this should be formalised as a proper implementation class or at least documented on the Javadocs so that we know what we're supposed to do. Something on getContent() should state the conditions under which the method will be called.
The ideal case for our own integration would be a new implementation class taking a callback object which is passed the stream.
As an aside, the isStreaming() method docs seem incomplete too. The three examples given are:
- Streamed entities that read data directly from the socket should return true.
- Self-contained entities should return false.
- Wrapping entities should delegate this call to the wrapped entity.
I assume true is correct in my case too? It was the case for the InputStream one.