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