[
https://issues.apache.org/jira/browse/CXF-4992?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Sergey Beryozkin resolved CXF-4992.
-----------------------------------
Resolution: Fixed
> proxy sub-resources creating wrong request URIs with non-HTTP transports
> ------------------------------------------------------------------------
>
> Key: CXF-4992
> URL: https://issues.apache.org/jira/browse/CXF-4992
> Project: CXF
> Issue Type: Bug
> Components: JAX-RS
> Affects Versions: 2.7.4
> Reporter: Adar Dembo
> Assignee: Sergey Beryozkin
> Fix For: 2.8.0, 2.5.11, 2.6.8, 2.7.5
>
>
> I was experimenting with direct dispatch local transport and ran into an
> issue with proxy-based clients.
> Here's my working WebClient-based client code:
> {code}
> 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();
> {code}
> Here's my broken proxy-based client code:
> {code}
> 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");
> {code}
> What breaks? I get an IllegalStateException with the message "Local
> destination does not have a MessageObserver on address /clusters". Note that
> the proxy-based client code works correctly when the address is
> "http://localhost:<port>/api", so I don't suspect anything broken in either
> the 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:
> {code}
> 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("/");
> }
> }
> {code}
> 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.
> I asked about this on the cxf-users mailing list
> (http://cxf.547215.n5.nabble.com/JAX-RS-recursive-dispatch-td5726752.html).
> The consensus was that this is a real bug, and likely affects other non-HTTP
> transports like JMS.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira