users@jersey.java.net

[Jersey] Re: Unable to get ChunkedOutput to work properly using Tomcat 7

From: Chun Tat David Chu <beyonddc.storage_at_gmail.com>
Date: Wed, 16 Oct 2013 18:11:51 -0400

Sure, my test application is actually fairly simple. Do you need it in
particular format?

I attached 4 files
For the web service, you'll need
AsyncPrototype.java
Person.java
web.xml

For the client, you will need
ChunkedInputTest.java

Thanks,

David

On Wed, Oct 16, 2013 at 5:01 AM, Marek Potociar
<marek.potociar_at_oracle.com>wrote:

> Hi David,
>
> We would need a reproducible test case to investigate further. Can you
> provide one?
>
> Thanks,
> Marek
>
> On Oct 12, 2013, at 3:41 AM, Chun Tat David Chu <
> beyonddc.storage_at_gmail.com> wrote:
>
> Hi Marek,
>
> Thank you for your valuable insight. I spent a little more time to re-read
> the Jersey's tutorial, and I saw the following statements...
> "Jersey provides several chunk parser implementation and you can implement
> your own parser to separate your chunks if you need. In our example above
> the default parser provided by Jersey is used that separates chunks based
> on presence of a \r\n delimiting character sequence."
>
> So I thought there is a default chunk parser in place if one is not
> provided or I misread the tutorial?
>
> I wrote a separate REST client using Apache HTTPComponents and when I
> enabled the debug, I see the following
>
> HttpResponseHandlerImpl.setContentType(): application/jsonHttpResponseHandlerImpl.setContentLength(): -158495 [main] DEBUG org.apache.http.wire - << "24[\r][\n]"58495 [main] DEBUG org.apache.http.wire - << "{"firstName":"David","lastName":"0"}"58495 [main] DEBUG org.apache.http.wire - << "[\r][\n]"58495 [main] DEBUG org.apache.http.wire - << "24[\r][\n]"58495 [main] DEBUG org.apache.http.wire - << "{"firstName":"David","lastName":"1"}"58495 [main] DEBUG org.apache.http.wire - << "[\r][\n]"58495 [main] DEBUG org.apache.http.wire - << "24[\r][\n]"58495 [main] DEBUG org.apache.http.wire - << "{"firstName":"David","lastName":"2"}"58501 [main] DEBUG org.apache.http.wire - << "[\r][\n]"58501 [main] DEBUG org.apache.http.wire - << "0[\r][\n]"58501 [main] DEBUG org.apache.http.wire - << "[\r][\n]"
>
> Based on those debug from the wire, it looks like each chunk contains a
> JSON object. If there is a default parser, how come the
> ChunkedInput.read() didn't return when a chunk is read but instead the
> ChunkedInput.read() was blocked until all the chunks are received?
>
> Thanks again!
>
> David
>
>
> On Fri, Oct 11, 2013 at 5:51 PM, Marek Potociar <marek.potociar_at_oracle.com
> > wrote:
>
>>
>> On Oct 11, 2013, at 4:13 PM, Chun Tat David Chu <
>> beyonddc.storage_at_gmail.com> wrote:
>>
>> Hi Marek,
>>
>> My test code on ChunkedOuput is not much different than the one in the
>> tutorial. It does write the chunk in a separate thread.
>> It spawns a new thread, sits in a loop and return 20 JSON objects. I
>> used the CountDownLatch just to make sure that the thread doesn't begin
>> until the method returned (see below).
>>
>>
>> @PUT
>> @Path("/asynchronous")
>> @Produces(MediaType.APPLICATION_JSON)
>> @Consumes(MediaType.APPLICATION_JSON)
>> public ChunkedOutput<Person> getAsyncResponse(Person rep) {
>>
>> System.out.println("Received: " + rep);
>>
>> final CountDownLatch countDownLatch1 = new CountDownLatch(1);
>>
>> final ChunkedOutput<Person> output = new
>> ChunkedOutput<Person>(String.class);
>>
>> new Thread() {
>> public void run() {
>> try {
>>
>> countDownLatch1.await();
>> Thread.sleep(2000);
>>
>> for (int i = 0; i < 20; i++) {
>>
>> Person person = new
>> Person("David",String.valueOf(i));
>> output.write(person);
>>
>> Thread.sleep(1000);
>> }
>> } catch (Throwable th) {
>> th.printStackTrace();
>> } finally {
>> try {
>> output.close();
>> } catch (IOException e) {
>> // TODO Auto-generated catch block
>> e.printStackTrace();
>> }
>> }
>> }
>> }.start();
>>
>> countDownLatch1.countDown();
>>
>> return output;
>> }
>>
>> My test client side is also very simple. Followed the tutorial and it
>> looks like this.
>> ClientConfig clientConfig = new ClientConfig();
>>
>> Client client = ClientBuilder.newClient();
>>
>> final Response response = client.target("
>> http://localhost:9080/jaxrs.prototype.tomcat7/rest/async/asynchronous
>> ").request(MediaType.APPLICATION_JSON).get();
>>
>>
>> final ChunkedInput<String> chunkedInput =
>> response.readEntity(new
>> GenericType<ChunkedInput<String>>() {});
>>
>>
>>
>> I think the problem is here - you need to set ChunkedInput parser (via
>> setParser(...)) to tell the chunk input where each chunk starts. For simple
>> cases you can try to use ChunkInput.createParser(...) methods to create a
>> fixed boundary delimiter parser. For anything more complex you may need to
>> implement a ChunkParser yourself.
>>
>> Marek
>>
>> String chunk = null;
>> chunk = chunkedInput.read();
>> while (chunk != null) {
>> System.out.println("Next chunk received: " + chunk);
>> chunk = chunkedInput.read();
>> }
>>
>> I am just not sure why it is not receiving a chunk at a time until all
>> the chunk is received then it print all 20 JSON objects at once.
>>
>> Thanks,
>>
>> David
>>
>> On Fri, Oct 11, 2013 at 4:43 AM, Marek Potociar <
>> marek.potociar_at_oracle.com> wrote:
>>
>>>
>>> On Oct 9, 2013, at 6:58 AM, Chun Tat David Chu <
>>> beyonddc.storage_at_gmail.com> wrote:
>>>
>>> Hi All,
>>>
>>> I am trying to get ChunkedOutput to work using Tomcat 7. My test code
>>> is very similar to what's available on the tutorial website.
>>> https://jersey.java.net/documentation/latest/async.html#chunked-output
>>>
>>>
>>> What is the difference between your code and the tutorial?
>>>
>>>
>>> I tried with both command line curl and a Java application that follows
>>> ChunkedInput tutorial
>>> https://jersey.java.net/documentation/latest/async.html#d0e7470
>>>
>>> By observing the behavior, it appears to me that my Java application is
>>> not receiving the chunked output whenever my web service is invoking
>>> chunkedOutput.write(). Instead all the chunked output is received at once
>>> after all the write is completed.
>>>
>>>
>>> It appears to me as though you are not using a separate thread to write
>>> the chunked data and trying to write all the chunks BEFORE you return your
>>> chunked output. Is that the case?
>>>
>>> In order order to receive new chunks immediately, you must first return
>>> the chunked output from your method and only then start writing new chunks.
>>>
>>> Marek
>>>
>>>
>>> Any one tried using ChunkedOutput with Tomcat 7? Is there anything that
>>> I must configure? or I need to use a different web server?
>>>
>>> Thanks!
>>>
>>> David
>>>
>>>
>>>
>>
>>
>
>