cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sergey Beryozkin <sberyoz...@gmail.com>
Subject Re: CXFServlet, Asynchronous JAX-RS server, Tomcat 7
Date Mon, 12 Nov 2012 17:49:32 GMT
I've ported the test for it to depend on Servlet3ContinuationProvider 
and I can reproduce the issue.

The problem seems that doing

suspend() -> resume() -> suspend()

does not work, the 2nd suspend() results in the async response completed 
without returning to JAXRS Invoker, where as the legacy Jetty 
Continuation provider works as expected.


Note, AsynResponse.setTimeout() calls cont.resume() so that the already 
suspended thread can be temporarily resumed in order to be suspended 
immediately with the application specified timeout. I guess this can be 
optimized by doing suspend() on the already suspended AsyncResponse, I 
haven't tried - will do later, but I think I'm seeing what you've also 
seen with your own update, specifically,

 >>It looks like that once timeout occurred, it's not "possible" to
 >> re-suspend the response again

Any ideas why this is the case with Servlet3 provider ?

Cheers, Sergey

On 12/11/12 14:09, Sergey Beryozkin wrote:
> Hi,
> On 12/11/12 12:23, Gege wrote:
>> I did try that.
>>
>> But it doesn't seems to be working. My client receives and empty
>> answer as soon as setTimeout is called, and the TimeoutHandler has no
>> effect.
>>
> I've updated the test that effectively relies on
> JettyContinuationProvider to start with the initial timeout, than use
> TimeoutHandler to extend the timeout twice (assuming the data is not
> available yet) and finally return a response.
> Also, I've updated AsyncResponseImpl to convert time units correctly,
> thanks for pointing to that bug:
>
> http://svn.apache.org/viewvc?rev=1408293&view=rev
>
>> I've been looking around in the code, and I noticed that the
>> handleTimeout method CANNOT be called back by the
>> "continuation-implementation-over-servlet3".
>>
>> In my "fix" (I'll send the java files to your personal email), looks
>> like I cannot send them there, I resorted to a trick.
>>
>> I made it so that :
>>
>> In Servlet3ContinuationProvider.java :: Servlet3Continuation.onTimeout
>> callback.onError(new TimeoutException());
>>
>> And in AsyncResponseImpl.java :: onError
>> if(error instanceof TimeoutException){
>> if(timeoutHandler != null){
>> timeoutHandler.handleTimeout(this);
>> }
>> }
>> else{
>> if (completionCallback != null) {
>> completionCallback.onError(error);
>> }
>> }
>>
>> It's not really clean, but in the Continuation interface there is no
>> way to forward the timeout event from the Servlet3ContinuationProvider
>> to AsyncResponsImpl. I suppose that's because CXF isn't directly using
>> the servlet3 asynchronous capabilities but making a Continuation
>> implementation over servlet3 because of legacy.
>>
>> However that fix was not enough because setTimeout calls resume, so
>> there is no wait the timout can ever happen. So I also changed the way
>> setTimeout works so that it does not calls resume, but
>> suspend(timeout).
>>
>> It looks like that once timeout occurred, it's not "possible" to
>> re-suspend the response again (however it's possible to change the
>> timeout value if it didn't fire yet). I'm not sure it's the correct
>> behaviour, but that's the way in behaves with my fix.
>>
> As far as JAX-RS application code is concerned, it should be able to
> extend the timeout (effectively do suspend the thread) as many times as
> needed.
>
>> I tested on Tomcat7 and JBoss AS 7.
>>
>> The timeouts are not very precise (around 1s of precision on tomcat,
>> and steps of 10s on jboss (setTimeout of 12s becomes 20s), but I guess
>> it is container-dependant.
>>
>> I'll send you the java files right after that mail. I'll let you do
>> the "diff".
>>
> OK, thanks for that, I'll experiment with the changes. What I'm going to
> do is to get the existing test also running with
> Servlet2ContinuationsProvider and see what happens :-)
>
> Cheers, Sergey
>
>> 2012/11/12 Sergey Beryozkin<sberyozkin@gmail.com>:
>>> Hi,
>>>
>>> thanks for the analysis so far, sorry for the lack of the documentation,
>>> still the work to do for me asap,
>>>
>>> On 08/11/12 15:00, gpasquiers.ext@orange.com wrote:
>>>>
>>>> Well, i still have an issue, so i'll continue on this thread.
>>>>
>>>> While handling my AsyncResponse I have the following issue :
>>>>
>>>> As soon as I call setTimeout(...) the AsyncResponse is "resumed" and
>>>> the
>>>> completionCallback is called.
>>>> Looks like that in CXF's AsyncResponseImpl (I look at the code to
>>>> understand) :
>>>> - setTimeout sets 'newTimeoutRequest' to true
>>>> - setTimeout callses resume()
>>>> * EXPECTED : the code expects 'handleTimeout' to be called (to then
>>>> suspend again the asyncResponse with the new timeout value)
>>>> * GUESSED : the "Continuation" impl assumes that everything is done
>>>> concerning the request (resume() was called) and calls the onComplete
>>>> callback (and sends an empty body in the answer).
>>>>
>>>> That being said, I can handle the timeouts on my own; but doesn't this
>>>> look like a bug ?
>>>>
>>> You need to do
>>>
>>> asyncResponse.setTimeout(2000, TimeUnit.MILLISECONDS);
>>> asyncResponse.setTimeoutHandler(new TimeoutHandlerImpl(id));
>>>
>>> where TimeoutHandler will decide what to do, extend the timeout, or
>>> provide
>>> a response, example:
>>>
>>> private class TimeoutHandlerImpl implements TimeoutHandler {
>>>
>>> private String id;
>>>
>>> public TimeoutHandlerImpl(String id) {
>>> this.id = id;
>>> }
>>>
>>> @Override
>>> public void handleTimeout(AsyncResponse asyncResponse) {
>>> asyncResponse.resume(books.get(id));
>>> }
>>>
>>> }
>>>
>>> where "id" is (in my test, a book id which was available when
>>> TimeoutHandlerImpl was created)
>>>
>>> With the handler the runtime is expected to return 503 only...
>>>
>>> Can you try it please ?
>>>
>>> Cheers, Sergey
>>>
>>>
>>>
>>>> -----Message d'origine-----
>>>> De : gpasquiers.ext@orange.com [mailto:gpasquiers.ext@orange.com]
>>>> Envoyé : jeudi 8 novembre 2012 15:05
>>>> À : users@cxf.apache.org
>>>> Objet : RE: CXFServlet, Asynchronous JAX-RS server, Tomcat 7
>>>>
>>>> Just after sending this mail I made the correct google-search and
>>>> noticed
>>>> I forgot to put the setting :
>>>>
>>>> <async-supported>true</async-supported>
>>>>
>>>> In the<servlet> definition in web.xml.
>>>>
>>>> ...
>>>>
>>>> *hides in a corner*
>>>>
>>>> So, now web.xml is :
>>>>
>>>> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
>>>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>>>> xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
>>>> http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
>>>> <servlet>
>>>> <servlet-name>CXFServlet</servlet-name>
>>>>
>>>> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
>>>>
>>>> <load-on-startup>1</load-on-startup>
>>>> <async-supported>true</async-supported>
>>>> </servlet>
>>>>
>>>> <servlet-mapping>
>>>> <servlet-name>CXFServlet</servlet-name>
>>>> <url-pattern>/cxf/*</url-pattern>
>>>> </servlet-mapping>
>>>> </web-app>
>>>>
>>>> The error disappeared, I have some issues sending the answer, but I
>>>> guess
>>>> it's totally related to my code !
>>>>
>>>> Hope it will save time to others.
>>>>
>>>> -----Message d'origine-----
>>>> De : gpasquiers.ext@orange.com [mailto:gpasquiers.ext@orange.com]
>>>> Envoyé : jeudi 8 novembre 2012 14:48
>>>> À : users@cxf.apache.org
>>>> Objet : CXFServlet, Asynchronous JAX-RS server, Tomcat 7
>>>>
>>>> Hi
>>>>
>>>> I'm currently trying to implement an asynchronous jax-rs server (the
>>>> client will be doing some long-polling, waiting for events, so I
>>>> don't want
>>>> to lock threads on the server).
>>>>
>>>> My target environment is JOnAS 5.2.1 (using Tomcat7 container), but I'm
>>>> first trying to make it work on a vanilla Tomcat7 (for now I have
>>>> the same
>>>> issue on both).
>>>>
>>>> The error I have is a NPE :
>>>>
>>>> Caused by: java.lang.NullPointerException
>>>> at
>>>> org.apache.cxf.jaxrs.impl.AsyncResponseImpl.<init>(AsyncResponseImpl.java:58)
>>>>
>>>> at
>>>> org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:650)
>>>>
>>>> at
>>>> org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:624)
>>>>
>>>> at
>>>> org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:224)
>>>>
>>>> at
>>>> org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:94)
>>>>
>>>> at
>>>> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
>>>>
>>>> ... 26 more
>>>>
>>>> I'm trying to use CXF the (I think) simplest way with simple
>>>> examples (see
>>>> end of mail).
>>>>
>>>> I've been looking around in the code, from what I've understood,
>>>> AsyncResponse is supposed to work with either :
>>>>
>>>> * jetty (provides a ContinuationProviderFactory on the bus)
>>>>
>>>> * servlets 3.0 (checks existence of method "isAsyncSupported" on
>>>> class ServletRequest)
>>>>
>>>> If neither of those conditions is met, then the NullPointerException
>>>> should happen.
>>>>
>>>> However I'm using tomcat 7 and it's supposed to work via the
>>>> servlets 3.0
>>>> support. So I'm guessing that maybe the servlet is still running on
>>>> servlet
>>>> 2.x despites being on tomcat 7, maybe that it's because I'm using
>>>> org.apache.cxf.transport.servlet.CXFServlet ? Or I missed a switch
>>>> somewhere
>>>> ?
>>>>
>>>> I'm quite stuck, but I'd really like to use this feature (asynchronous
>>>> server-side) for JAX-RS (and then to see if there is something
>>>> similar for
>>>> JAX-WS).
>>>>
>>>> Thanks in advance!!!
>>>>
>>>>
>>>>
>>>> web.xml (to start cxf-servlet)
>>>>
>>>> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
>>>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>>>> xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
>>>> http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
>>>> <servlet>
>>>> <servlet-name>CXFServlet</servlet-name>
>>>>
>>>> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
>>>>
>>>> <load-on-startup>1</load-on-startup>
>>>> </servlet>
>>>>
>>>> <servlet-mapping>
>>>> <servlet-name>CXFServlet</servlet-name>
>>>> <url-pattern>/cxf/*</url-pattern>
>>>> </servlet-mapping>
>>>> </web-app>
>>>>
>>>> cxf-servlet.xml (default spring definition)
>>>>
>>>> <beans xmlns="http://www.springframework.org/schema/beans"
>>>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>>>> xmlns:jaxws="http://cxf.apache.org/jaxws"
>>>> xmlns:jaxrs="http://cxf.apache.org/jaxrs"
>>>> xsi:schemaLocation="
>>>> http://www.springframework.org/schema/beans
>>>>
>>>> http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
>>>> http://cxf.apache.org/jaxws
>>>> http://cxf.apache.org/schemas/jaxws.xsd
>>>> http://cxf.apache.org/jaxrs
>>>> http://cxf.apache.org/schemas/jaxrs.xsd">
>>>>
>>>> <import resource="classpath:META-INF/cxf/cxf.xml"/>
>>>> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
>>>>
>>>> <jaxws:endpoint id="greeter"
>>>> implementor="com.mycompany.demo.StockQuoteReporter"
>>>> address="/StockQuoteReporter"/>
>>>>
>>>> <jaxrs:server id="helloworlder"
>>>> serviceClass="demo.rs.server.HelloWorldResource"
>>>> address="/helloworld"/> </beans>
>>>>
>>>> HelloWorldResource.java
>>>>
>>>> // some imports...
>>>>
>>>> @Path("/say")
>>>> public class HelloWorldResource {
>>>>
>>>> @GET
>>>> @Produces("text/plain")
>>>> public void helloWorld(AsyncResponse asyncResponse) {
>>>> asyncResponse.setTimeout(1000, TimeUnit.MILLISECONDS);
>>>> asyncResponse.setTimeoutHandler(new TimeoutHandler() {
>>>> public void handleTimeout(AsyncResponse ar) {
>>>> ar.resume("timeout");
>>>> }
>>>> });
>>>> }
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>> _________________________________________________________________________________________________________________________
>>>>
>>>>
>>>> Ce message et ses pieces jointes peuvent contenir des informations
>>>> confidentielles ou privilegiees et ne doivent donc pas etre diffuses,
>>>> exploites ou copies sans autorisation. Si vous avez recu ce message par
>>>> erreur, veuillez le signaler a l'expediteur et le detruire ainsi que
>>>> les
>>>> pieces jointes. Les messages electroniques etant susceptibles
>>>> d'alteration,
>>>> France Telecom - Orange decline toute responsabilite si ce message a
>>>> ete
>>>> altere, deforme ou falsifie. Merci.
>>>>
>>>> This message and its attachments may contain confidential or privileged
>>>> information that may be protected by law; they should not be
>>>> distributed,
>>>> used or copied without authorisation.
>>>> If you have received this email in error, please notify the sender and
>>>> delete this message and its attachments.
>>>> As emails may be altered, France Telecom - Orange is not liable for
>>>> messages that have been modified, changed or falsified.
>>>> Thank you.
>>>>
>>>>
>>>>
>>>> _________________________________________________________________________________________________________________________
>>>>
>>>>
>>>> Ce message et ses pieces jointes peuvent contenir des informations
>>>> confidentielles ou privilegiees et ne doivent donc pas etre diffuses,
>>>> exploites ou copies sans autorisation. Si vous avez recu ce message par
>>>> erreur, veuillez le signaler a l'expediteur et le detruire ainsi que
>>>> les
>>>> pieces jointes. Les messages electroniques etant susceptibles
>>>> d'alteration,
>>>> France Telecom - Orange decline toute responsabilite si ce message a
>>>> ete
>>>> altere, deforme ou falsifie. Merci.
>>>>
>>>> This message and its attachments may contain confidential or privileged
>>>> information that may be protected by law; they should not be
>>>> distributed,
>>>> used or copied without authorisation.
>>>> If you have received this email in error, please notify the sender and
>>>> delete this message and its attachments.
>>>> As emails may be altered, France Telecom - Orange is not liable for
>>>> messages that have been modified, changed or falsified.
>>>> Thank you.
>>>>
>>>>
>>>>
>>>> _________________________________________________________________________________________________________________________
>>>>
>>>>
>>>> Ce message et ses pieces jointes peuvent contenir des informations
>>>> confidentielles ou privilegiees et ne doivent donc
>>>> pas etre diffuses, exploites ou copies sans autorisation. Si vous avez
>>>> recu ce message par erreur, veuillez le signaler
>>>> a l'expediteur et le detruire ainsi que les pieces jointes. Les
>>>> messages
>>>> electroniques etant susceptibles d'alteration,
>>>> France Telecom - Orange decline toute responsabilite si ce message a
>>>> ete
>>>> altere, deforme ou falsifie. Merci.
>>>>
>>>> This message and its attachments may contain confidential or privileged
>>>> information that may be protected by law;
>>>> they should not be distributed, used or copied without authorisation.
>>>> If you have received this email in error, please notify the sender and
>>>> delete this message and its attachments.
>>>> As emails may be altered, France Telecom - Orange is not liable for
>>>> messages that have been modified, changed or falsified.
>>>> Thank you.
>>>>
>>>

Mime
View raw message