cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Sergey Beryozkin" <sergey.beryoz...@progress.com>
Subject Re: Jetty Continuations in CXF
Date Mon, 03 Nov 2008 14:41:59 GMT
Hi,

>
> I guess my thinking was to tie the continutations directly to the
> PhaseInterceptorChain (since that is going to need to know about them
> anyway).   However, I suppose it could easily be done with a new interface.
> Probably the best thing to do is to stub out a sample usecase.   So here
> goes.....
>
> Lets take a "GreetMe" web service that in the greetMe method will call off
> asynchrously to some JMS service to actually get the result.
>
> @Resource(name = "jmsClient")
> Greeter jmsGreeter
> @Resource
> WebServiceContext context;
> public String greetMe(String arg) {
>     ContinuationSupport contSupport = (ContinuationSupport)
>              context.get(ContinuationSupport.class.getName());
>     if (contSupport == null) {
>          //continuations not supported, must wait
>          return jmsGreeter.greetMe(arg);
>     }
>     Continuation cont = contSupport.getContinuation();
>     if (cont.isResumed()) {
> AsyncHandler<GreetMeResponse> handler = cont.getObject();
>        return handler.get().getReturn();
>     } else {
>         AsyncHandler<GreetMeResponse> handler = new Handler(cont);
>         jmsGreeter.greetMeAsync(arg, handler);
>         cont.suspend(handler);
> return null;   //won't actually get here as suspend will throw a
> ContinuationException
>     }
> }
>
> The Handler would look something like:
> class Handler implements AsyncHandler<GreetMeResponse> {
> GreetMeResponse resp;
>        Continuation cont;
> public Handler(Continuation cont) {
>            this.cont = cont;
>        }
>        public void handleResponse(Response<GreetMeLaterResponse> response) {
>              resp = response.get();
>              cont.resume();
>       }
> }
>

It's an interesting idea. Worth having it in mind. However, I'm thinking, how reasonable it
is to expect that a user would want to 
write a Continuations code portable across multiple transports ? I'd imagine that a user which
wishes to do explicit continuations 
would do them with HTTP transport in mind, well, at least now that Jetty Continuations are
available, with Servlet 3.0 supporting 
suspended invocations too. Otherwise we'd need to come up with our own ContiniationsSupport
and Continuation classes - that's why 
would user use JettyContiations support and expect ths code work say with JMS or indeed with
some other transport other than HTTP ?

I think we have two scenarious to look at. First one is when a CXF acts as a request provider
for some ServiceMix components 
(implicitly serving as 'application code') - which is what CXF-1835 is mostly about.

Another one is about CXF service application code doing Continuations explicitly. I think
it's a more advanced issue to deal with 
and your suggestion is about dealing with this second issue, this is how I see it anyway.
And it attempts to do it with the 
portability in mind.

At this stage I'd like to focus on the first case which would be equivalent to a user doing
jetty Continuations explicitly (which is 
what SMX does) :

import org.mortbay.util.ajax.ContinuationSupport;
import org.mortbay.util.ajax.Continuation;

@Resource
WebServiceContext context;
public String greetMe(String arg) {
    Continuation cont = context.get(Continuation.class.getName());

    if (cont.isResumed()) {
          AsyncHandler<GreetMeResponse> handler = cont.getObject();
          return handler.get().getReturn();
    } else {
           Continuation cont =  ContinuationSupport.getContinuation();
           AsyncHandler<GreetMeResponse> handler = new Handler(cont);
           jmsGreeter.greetMeAsync(arg, handler);
           cont.suspend(handler);
           return null;
    }
}



> Basically, the HTTP/Jetty transport could provide an implementation of
> ContinuationSupport that wrappers the jetty stuff.    JMS could provide one
> that's pretty much a null op.   Transports that cannot support it (like
> servlet) just wouldn't provide an implementation.
>
>
> Does that make sense?   Other ideas?

I think it does - but I'd just like to start with just HTTP in mind, just to get going and
consider a transport portability issue at 
the the next stage.

Cheers, Sergey

>
> Dan
>
>
>
>
> On Friday 24 October 2008 9:58:08 am Sergey Beryozkin wrote:
>> > No.   We don't want that.   Whatever we do should work for other
>> > transports as well like JMS.  Thus, this shouldn't be tied to jetty
>> > continuations directly.
>>
>> No, I'm not suggesting to tie it up to jetty continuations.
>> Ex.
>>
>> try {
>>   invoke(); // continuation.suspend() somehow by the code being invoked
>> upon }
>> catch (RuntimeException ex) {
>>
>> if (ex.getClass().getName().equals("jetty.JettyContinuationException"))
>>     throw new SuspendedFault(ex);
>>     // or PhaseInterceptorChain.suspend()
>> }
>> }
>>
>> > Most likely, we could add a "suspend()" method to PhaseInterceptorChain
>> > that would do something very similar and throw a "SuspendException" or
>> > something in the same package as PhaseInterceptorChain.
>>
>> When do we trigger this PhaseInterceptorChain.suspend() call though ?
>>
>> >   That would get propogated
>> > back to the JettyDestination that could then call the jetty things.   The
>> > JMS transport could just catch it and more or less ignore it.    We'd
>> > then have to add a "resume()" method to the chain which would call back
>> > onto a listener that the transport provides.   Jetty would just call the
>> > jetty resume stuff. JMS would probably put a runnable on the workqueue to
>> > restart the chain.
>>
>> ok
>>
>> > Also, suspend() would need to check if there is a listener.  If not, it
>> > should not throw the exception.   Thus, the servlet transport and CORBA
>> > stuff that couldn't do this would pretty much just ignore it.
>>
>> ok, not sure I understand about the listener but I think I see what you
>> mean...
>>
>> > Basically, this needs to be done in such a way that it CAN work for the
>> > non-jetty cases.   However, it also needs to be done in a way that
>> > doesn't affect existing transports.
>>
>> +1
>>
>> Cheers, Sergey
>>
>> > Dan
>> >
>> >> 2. Now, if the above can be figured out, the next problem arises: when
>> >> the "trigger" to wake up the continuation occurs
>> >>
>> >> I think we can can do in JettyDestination omething similar to what is
>> >> done in SMX. When getting a SuspendedFault exception, we can extract
>> >> from it the original continuation instance or else we can do
>> >> ContinuationSupport.getContinuation(request) which should return us the
>> >> instance. At this point we can use it as a ket to store the current
>> >> exchange plus all the other info we may need.
>> >>
>> >> When the user/application code does continuation.resume(), the Jetty
>> >> thread will come back and we will use the
>> >> ContinuationSupport.getContinuation(request) to get us the active
>> >> continuation and use it to extract the suspended exchange and proceed
>> >> from there, say we'll call PhaseInterceptorPhase.resume(), etc,
>> >> something along the lines you suggested
>> >>
>> >>
>> >> 3. Basically, to do this "right", we'd need to audit pretty much
>> >> everything to make sure nothing is stored on the stack and is
>> >> "resumable". Once that is done, the rest is relatively easy.
>> >>
>> >> Yea - probably can be the quite challenging
>> >>
>> >>
>> >> Thoughts ?
>> >>
>> >> Cheers, Sergey
>> >>
>> >>
>> >>
>> >>
>> >> [1] http://docs.codehaus.org/display/JETTY/Continuations
>> >> [2] https://issues.apache.org/jira/browse/CXF-1835
>> >> [3]
>> >> https://issues.apache.org/jira/browse/CXF-1835?focusedCommentId=12642361
>> >>#ac tion_12642361
>> >
>> > --
>> > Daniel Kulp
>> > dkulp@apache.org
>> > http://dankulp.com/blog
>
>
>
> -- 
> Daniel Kulp
> dkulp@apache.org
> http://dankulp.com/blog 


Mime
View raw message