Details
Description
A service in question needs to be reachable via multiple paths. The @Path param allows for regex matching on a class-level like the following: @Path("/{a:cat|dog}"). The class in which this annotation is used will correctly take requests at either /cat or /dog. A class-level @PathParam is created by the name of a.
The issue comes when creating a proxy for this service through the JAXRSClientFactoryBean.java create method shown below:
// @param varValues optional list of values which will be used to substitute // template variables specified in the class-level JAX-RS Path annotations public <T> T create(Class<T> cls, Object... varValues) { return cls.cast(createWithValues(varValues)); }
To define the value of the @PathParam a that this proxy should use, it appears as if the Object... varValues needs to be populated. The ClientProxyImpl is created with the following, after the ClientState is retrieved:
protected ClientProxyImpl createClientProxy(ClassResourceInfo cri, boolean isRoot, ClientState actualState, Object[] varValues) { if (actualState == null) { return new ClientProxyImpl(URI.create(getAddress()), proxyLoader, cri, isRoot, inheritHeaders, getProperties(), varValues); } else { return new ClientProxyImpl(actualState, proxyLoader, cri, isRoot, inheritHeaders, getProperties(), varValues); } }
In this scenario, actualState is defined, and getProperties() returns null. varValues is populated with one entry, "dog". The constructor for the ClientProxyImpl in this situation is:
public ClientProxyImpl(ClientState initialState, ClassLoader loader, ClassResourceInfo cri, boolean isRoot, boolean inheritHeaders, Object... varValues) { ... }
The key here is that the result of getProperties() will be the first entry in the Object[] created by the var args.
After the initValuesMap(Object... varValues) is called, I would expect the valuesMap to have one entry, a mapping of "a" to "dog" so that when the proxy is used, it will populate the @PathParam a with "dog" automatically. What ends up happening is because the null properties is being passed as part of the Object... varValues to the ClientProxyImpl constructor, the varValues turns into an array of [null, "dog"] instead of the expected ["dog"]. The proxy creates successfully but does not work because the valuesMap ends up mapping "a" to null. This breaks the URI builder implementation with an IllegalArgumentException:
private URI doBuild(boolean fromEncoded, boolean encodePathSlash, Object... values) { if (values == null) { throw new IllegalArgumentException("Template parameter values are set to null"); } for (int i = 0; i < values.length; i++) { if (values[i] == null) { throw new IllegalArgumentException("Template parameter value at position " + i + " is set to null"); } } ... }
This change to the createClientProxy method was made here: https://github.com/apache/cxf/pull/572 and maybe needs to be addressed.
Attachments
Issue Links
- links to