cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sergey Beryozkin <sberyoz...@gmail.com>
Subject Re: JAX-RS recursive dispatch?
Date Mon, 29 Apr 2013 15:41:14 GMT
Hi
On 29/04/13 16:34, Adar Dembo wrote:
> Thanks guys. Should I file a JIRA, or is there already one open on this?
>
Please open the one, many thanks

Sergey

>
> On Sun, Apr 28, 2013 at 11:25 AM, Sergey Beryozkin<sberyozkin@gmail.com>wrote:
>
>> Hi Andrei
>>
>> On 28/04/13 13:45, Andrei Shakirin wrote:
>>
>>> Looks like as a bug for me.
>>> What do you think, Sergey?
>>>
>>>   You are right, it is a bug indeed with the way subresource proxies build
>> request URIs, we probably need to update that constructor a bit
>>
>> Thanks, Sergey
>>
>>> Cheers,
>>> Andrei.
>>>
>>>   -----Original Message-----
>>>> From: Adar Dembo [mailto:adar@cloudera.com]
>>>> Sent: Samstag, 27. April 2013 04:27
>>>> To: Sergey Beryozkin
>>>> Cc: users@cxf.apache.org
>>>> Subject: Re: JAX-RS recursive dispatch?
>>>>
>>>> Sergey,
>>>>
>>>> Local transport certainly looks promising. I set it up with direct
>>>> dispatch and,
>>>> as far as I can tell, it looks like the calling thread is also
>>>> responsible for method
>>>> dispatch. That's awesome.
>>>>
>>>> Now for the bad news. I got a toy example working with the WebClient API.
>>>> The client-side code looks something like this:
>>>>
>>>>         WebClient client = WebClient.create("local://api"**);
>>>>
>>>> WebClient.getConfig(client).**getRequestContext().put(**
>>>> LocalConduit.DIRECT_
>>>> DISPATCH,
>>>> Boolean.TRUE);
>>>>         client.path("v1/clusters/not-**a-valid-cluster");
>>>>         client.get();
>>>>
>>>> However, I can't get it working with the proxy-based client. My code
>>>> looks
>>>> like this:
>>>>
>>>>       JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
>>>>       bean.setAddress("local://api")**;
>>>>       bean.setResourceClass(**ApiRootResourceImpl.class);
>>>>       ApiRootResource root = bean.create(**ApiRootResourceImpl.class);
>>>>       ClientConfiguration config = WebClient.getConfig(root);
>>>>       config.getRequestContext().**put(LocalConduit.DIRECT_**DISPATCH,
>>>> Boolean.TRUE);
>>>>       config.getConduit();
>>>>
>>>> root.getRootV1().**getClustersResource().**readCluster("not-a-valid-**
>>>> cluster");
>>>>
>>>>    I keep getting an IllegalStateException with the message "Local
>>>> destination
>>>> does not have a MessageObserver on address /clusters". Note that this
>>>> same code works correctly when the address is
>>>> "http://localhost:<port>/api", so I don't suspect anything broken in
>>>> either
>>>> the client code or in my resource layout.
>>>>
>>>> I've spent a fair amount of time debugging this and I think I've figured
>>>> out
>>>> what's going on. Every method call into the proxy (getRootV1(),
>>>> getClustersResource(), and readCluster()) creates a new proxy for the
>>>> corresponding subresource. That involves creating a new LocalClientState
>>>> (see ClientProxyImpl.invoke() for details). Here is its constructor:
>>>>
>>>>       public LocalClientState(URI baseURI) {
>>>>           this.baseURI = baseURI;
>>>>           String scheme = baseURI.getScheme();
>>>>           if (!StringUtils.isEmpty(scheme)&**&
>>>>   scheme.startsWith(HTTP_SCHEME)**)
>>>>
>>>> {
>>>>               this.currentBuilder = UriBuilder.fromUri(baseURI);
>>>>           } else {
>>>>               this.currentBuilder = UriBuilder.fromUri("/");
>>>>           }
>>>>       }
>>>>
>>>> Because the baseURI in question begins with "local://", we end up in the
>>>> 'else' statement, which resets our URI's path to '/'. In my case, the
>>>> URIs for
>>>> each subcall end up looking like "/", "/v1", and "/clusters" instead of
>>>> "local://api", "local://api/v1", and "local://api/v1/clusters".
>>>>
>>>> Later, during conduit selector preparation (called from inside
>>>> ClientProxyImpl.**doChainedInvocation, via createMessage()), we try to
>>>> find a
>>>> "compatible" conduit. We only have one conduit: a LocalConduit
>>>> constructed
>>>> during the call to config.getConduit() in the client code. The conduit is
>>>> "compatible" if its endpoint's address matches the address in the
>>>> message.
>>>> And the address in the message is based on those partial URIs I described
>>>> earlier. So what happens? The LocalConduit's endpoint's address is
>>>> "local://api", but the address in the message is "/clusters". They don't
>>>> match,
>>>> and findCompatibleConduit() fails. We then construct a new LocalConduit
>>>> on-
>>>> the-fly (see AbstractConduitSelector.**getSelectedConduit()),
>>>> but the LocalDestination that's created for it (by LocalTransportFactory)
>>>> never gets an observer installed in it. The original LocalConduit (the
>>>> one that
>>>> didn't match) has a destination with an observer; it was set up in
>>>> ServerImpl.start().
>>>>
>>>> Now, I was able to make forward progress by, using my debugger, modifying
>>>> LocalClientState.**currentBuilder in every proxy call to be an absolute
>>>> path like
>>>> "local://api/...". At that point, the exception went away and the message
>>>> was routed to the server. But then
>>>> JAXRSInInterceptor.**processMessage() failed to find the method to
>>>> dispatch,
>>>> so I suspect I broke something in the process.
>>>>
>>>> So, am I crazy? Or do proxy-based clients not work correctly with a local
>>>> transport? I'm using CXF 2.7.4.
>>>>
>>>>
>>>> On Fri, Apr 26, 2013 at 1:58 AM, Sergey Beryozkin
>>>> <sberyozkin@gmail.com>wrote:
>>>>
>>>>   On 26/04/13 09:48, Sergey Beryozkin wrote:
>>>>>
>>>>>   Hi,
>>>>>> On 26/04/13 00:11, Adar Dembo wrote:
>>>>>>
>>>>>>   Thanks for the suggestion.
>>>>>>>
>>>>>>> Will using the WebClient in this way open a socket over the host's
>>>>>>> loopback interface? Since I'm keeping a database transaction
open
>>>>>>> (via
>>>>>>> Hibernate) during this time, it's important that 1. the latency
in
>>>>>>> the batch calls be minimal, and 2. the calls themselves be made
by
>>>>>>> the same thread as the one that serviced the batch endpoint.
Can I
>>>>>>> configure the WebClient in some way to get these guarantees?
>>>>>>>
>>>>>>>    I'm not sure we can have the current thread which invokes
on the
>>>>>>>
>>>>>> endpoint run that endpoint's own external call completely.
>>>>>>
>>>>>> Actually, if we get WebClient use CXF's Async HTTP Conduit (Apache
>>>>>> HTTP Client based), using WebClient#async switch to JAX-RS 2.0
>>>>>> AsyncInvoker (starting from CXF 2.7.0), then I guess we won't have
a
>>>>>> single thread involved, otherwise it should be a single thread. Dan,
>>>>>> clarify please if it is not quite the case.
>>>>>>
>>>>>> I don't think we have any control over what happens at the socket
>>>>>> level, unless... Are you dealing with the the same host outbound
>>>>>> calls ? If yes
>>>>>> - try using the local transport:
>>>>>>
>>>>>> https://cwiki.apache.org/****confluence/display/CXF20DOC/**<https://cwiki.apache.org/**confluence/display/CXF20DOC/**>
>>>>>> JAXRS+Testing#JAXRSTesting-
>>>>>>
>>>>> **LocalTransport<https://**cwiki.apache.org/<https://cwiki.apache.org/>
>>>>
>>>>> JAXRS+confluence/display/**CXF20DOC/JAXRS+Testing#**JAXRSTesting-
>>>>>>
>>>>> LocalTra
>>>>
>>>>> JAXRS+nsport>
>>>>>>
>>>>>> http://svn.apache.org/repos/****asf/cxf/trunk/systests/jaxrs/****<http://svn.apache.org/repos/**asf/cxf/trunk/systests/jaxrs/**>
>>>>>> src/test/java/org/apache/cxf/****systest/jaxrs/**
>>>>>> JAXRSLocalTransportTest.java<h**ttp://svn.apache.org/repos/**
>>>>>> asf/cxf/trun<http://svn.apache.org/repos/asf/cxf/trun>
>>>>>> k/systests/jaxrs/src/test/**java/org/apache/cxf/systest/**
>>>>>> jaxrs/JAXRSLoca
>>>>>> lTransportTest.java>
>>>>>>
>>>>>>
>>>>>> Finally, on the server, try using JAX-RS 2.0 AsyncDispatch (best
from
>>>>>> CXF 2.7.4), that may help on its own, I'll work on documenting all
>>>>>> 2.0 features asap.
>>>>>>
>>>>>>   Sorry, meant AsyncResponse:
>>>>> https://jax-rs-spec.java.net/****nonav/2.0-SNAPSHOT/apidocs/**<https://jax-rs-spec.java.net/**nonav/2.0-SNAPSHOT/apidocs/**>
>>>>> javax/ws/rs/container/****AsyncResponse.html<https://**
>>>>> jax-rs-spec.java.ne<https://jax-rs-spec.java.ne>
>>>>> t/nonav/2.0-
>>>>>
>>>> SNAPSHOT/apidocs/javax/ws/rs/**container/AsyncResponse.html>
>>>>
>>>>>
>>>>>
>>>>>   Sergey
>>>>>>
>>>>>>
>>>>>
>>
>> --
>> Sergey Beryozkin
>>
>> Talend Community Coders
>> http://coders.talend.com/
>>
>> Blog: http://sberyozkin.blogspot.com
>>
>


Mime
View raw message