[ 
https://issues.apache.org/jira/browse/CXF-8556?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Noah Rickles updated CXF-8556:
------------------------------
    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:
{code:java}
// @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)); }{code}
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:
{code:java}
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);     
     }
}
{code}
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:
{code:java}
public ClientProxyImpl(ClientState initialState,
 ClassLoader loader,
 ClassResourceInfo cri,
 boolean isRoot,
 boolean inheritHeaders,
 Object... varValues) { ... }
{code}
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}}:
{code:java}
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"); }
}
...
 }
{code}
 

This change to the {{createClientProxy}} method was made here: 
[https://github.com/apache/cxf/pull/572|https://github.com/apache/cxf/pull/572.]
 and maybe needs to be addressed.

  was:
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:
{code:java}
// @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)); }{code}
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:
{code:java}
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);     
     }
}
{code}
In this scenario, {{actualState}} is defined, and {{getProperties()}} returns 
{{null}}. {{varValues}} is populated with {{{"dog"}}}. The constructor for the 
{{ClientProxyImpl}} in this situation is:
{code:java}
public ClientProxyImpl(ClientState initialState,
 ClassLoader loader,
 ClassResourceInfo cri,
 boolean isRoot,
 boolean inheritHeaders,
 Object... varValues) { ... }
{code}
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}}:
{code:java}
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"); }
}
...
 }
{code}
 

This change to the {{createClientProxy}} method was made here: 
[https://github.com/apache/cxf/pull/572|https://github.com/apache/cxf/pull/572.]
 and maybe needs to be addressed.


> Null AbstractEndpointFactory Properties Interferes with Class-Level PathParam 
> When Creating Proxies with Defined ClientState
> ----------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CXF-8556
>                 URL: https://issues.apache.org/jira/browse/CXF-8556
>             Project: CXF
>          Issue Type: Bug
>          Components: JAX-RS
>    Affects Versions: 3.4.4
>            Reporter: Noah Rickles
>            Priority: Major
>              Labels: Bug
>
> 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:
> {code:java}
> // @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)); }{code}
> 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:
> {code:java}
> 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);     
>      }
> }
> {code}
> 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:
> {code:java}
> public ClientProxyImpl(ClientState initialState,
>  ClassLoader loader,
>  ClassResourceInfo cri,
>  boolean isRoot,
>  boolean inheritHeaders,
>  Object... varValues) { ... }
> {code}
> 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}}:
> {code:java}
> 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"); }
> }
> ...
>  }
> {code}
>  
> This change to the {{createClientProxy}} method was made here: 
> [https://github.com/apache/cxf/pull/572|https://github.com/apache/cxf/pull/572.]
>  and maybe needs to be addressed.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to