>
> Thanks guys. Should I file a JIRA, or is there already one open on this?
>
>>
>>  Please open the one, many thanks
>

Filed CXF-4992.

On Sun, Apr 28, 2013 at 11:25 AM, Sergey Beryozkin<[email protected]**
>> >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:[email protected]]
>>>>> Sent: Samstag, 27. April 2013 04:27
>>>>> To: Sergey Beryozkin
>>>>> Cc: [email protected]
>>>>> 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
>>>>> <[email protected]>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/**>
>>>>>>> **<https://cwiki.apache.org/****confluence/display/CXF20DOC/**<https://cwiki.apache.org/**confluence/display/CXF20DOC/**>
>>>>>>> **>
>>>>>>> JAXRS+Testing#JAXRSTesting-
>>>>>>>
>>>>>>>  
>>>>>>> **LocalTransport<https://**cwi**ki.apache.org/<http://cwiki.apache.org/>
>>>>>> <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/****>
>>>>>>> <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/****<http://svn.apache.org/repos/**>
>>>>>>> asf/cxf/trun<http://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/**>
>>>>>> <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<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
>>>
>>>
>>
>

Reply via email to