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: Fri, 11 Oct 2013 21:41:14 -0400

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
>>
>>
>>
>
>