Great !

I'll try it out a bit this evening. But probably nothing you already
tested. I'm still at experimenting on the features i'll need; i don't
have a "complete" application yet.

Anyway, thanks for the fix ! Let's make those useful async features usable :-)

2012/11/14 Sergey Beryozkin <[email protected]>:
> Hi
>
> On 13/11/12 22:24, Gege wrote:
>>
>> It's kind of getting too far in CXF's core for me.
>> At least I understand what you said bout re-dispatching the message,
>> sorry for disagreeing before...
>>
> no problems and thanks for spending the time on it
>
>
>> ---------
>> Short version of what i think now :
>> When "resume-suspend", the request re-goes through doGet and when
>> calling startAsync a new AsyncContext is created.
>> We HAVE to keep the same Servlet3Continuation object because the
>> AsyncResponseImpl has a reference to it.
>> I think that the best way to keep the same Servlet3Continuation
>> (AsyncListener) is by using the onStartAsync event (that's what it's
>> made for).
>>
>> So we might "just" need to know this request is "special" and call
>> startAsync on it. The onStartAsync would handle the "switch" from the
>> older context to the newer one.
>>
>> However : i don't know of to make the internal mechanics of CXF behave
>> properly... and if I'm right.
>> ---------
>> Log version with some code :
>>
>> I played with simple async servlet 3 and understood how to re-pause a
>> message.
>> You have to dispatch() it, so that it's dispatched a second time,
>> exactly the sameway. However, you have to know that it's not the first
>> time you receive it so that you handle it in a different way.
>>
>> Here is what i began to do :
>>
>> I think we have to use the startAsync() method of the AsyncListener.
>> It's made so that you can re-register the same listener to the new
>> AsyncContext whete startAsync is called a second time on a request.
>>
>>          @Override
>>          public void onStartAsync(AsyncEvent event) throws IOException {
>>              System.out.println("onStartAsync");
>>              // a new startAsync happened (request was dispatched again)
>>              // but request was not resumed (isPending), so we assume it's
>>              // still paused
>>              if (isPending) {
>>                  // re-register ourselve so that AsyncResponseImpl's
>> reference
>>                  // to this continuation is still valid
>>                  event.getAsyncContext().addListener(this);
>>
>>                  // copy the old context's timout to the new context
>>                  event.getAsyncContext().setTimeout(context.getTimeout());
>>
>>                  // now replace old context reference by the new one
>>                  context = event.getAsyncContext();
>>              }
>>          }
>>
>> I think it's necessary to keep the same Continuation object (the same
>> AsyncListener) so that the AsyncResponseImpl's reference to the
>> Continuation object stay valid (for the resume / suspend actions ...).
>> And the onStartAsync is probably the only way to do it.
>>
>> So, I also modified the constructor of the Servlet3Continuation so
>> that it just calls startAsync when beeing created (should trigger the
>> onStartAsync of the old Servlet3Continuation, and thus making it valid
>> again because it will register itself against the new AsyncContext).
>>
>>              if (isNew) {
>>                  // untouched code
>>              } else {
>>                  req.startAsync(req, resp);
>>              }
>>
>> Problems :
>>   - This newly created Servlet3Continuation is now useless (memory
>> leak.. invalid reference inside of CXF ?)
>>   - I tried this but i get a NPE in the PhaseInterceptorChain, probably
>> linked to the "State" of the message... I don't know about the details
>> ...
>>
>> I hope this helps you more than the previous messages.
>
>
> It does. Believe it or not but I've got my Servlet3 tests working now, after
> making the changes (based on your feedback):
>
> http://svn.apache.org/viewvc?rev=1409193&view=rev
>
> It does appear that "req.startAsync()" is really what is needed to get the
> same context (debugger shows it is actually the same reference that is
> returned) prepared again, the code does "context = req.startAsync();" just
> in case, but looks like the same ref is supposed to be returned anyway,
> given that req.startAsync() operates on the earlier provided servlet
> request/response objects.
>
> Also, setting a listener after 'req.startAsync()' does not seem to make any
> difference, timeouts are observed and then re-dispatches occur with or
> without this registration, so it looks like registering a listener is only
> required during the initial context initialization in the constructor.
>
> Can you please experiment with this code in Tomcat ? System tests rely on
> Jetty Servlet3 async context implementation.
>
> Dan, others, please review the above change and let me know if you have any
> concerns
>
> Thanks, Sergey
>
>
>
>
>

Reply via email to