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

Neena Jacob updated CXF-9235:
-----------------------------
    Description: 
{{InvocationBuilderImpl.property()}} stores request properties in a nested map 
under the key {{jaxrs.filter.properties}} inside the WebClient request context. 
When a client calls:

 
{{builder.property("set.content.type.for.empty.request", "FALSE")}}
 
the value is stored inside that nested map, not at the top level of the request 
context.

However, {{Headers.setProtocolHeadersInConnection()}} retrieves the property 
via 
{{{}message.getContextualProperty("set.content.type.for.empty.request"){}}}, 
which builds a merged context cache from Bus → Service → Endpoint → Exchange → 
Message using shallow {{putAll()}} calls. The nested 
{{jaxrs.filter.properties}} map is present in the cache as an opaque {{Map}} 
value under that key, but its contents are never unpacked. Consequently, 
{{getContextualProperty()}} returns {{{}null{}}}, the 
{{set.content.type.for.empty.request}} configuration is silently ignored, and 
the {{Content-Type}} header is always added to non-GET requests with an empty 
entity body.

*Working scenario (for contrast):*

Setting the property at the {{Client}} or {{WebTarget}} level works correctly:

 
{{client.property("set.content.type.for.empty.request", "FALSE")// 
orwebTarget.property("set.content.type.for.empty.request", "FALSE")}}
 
This goes through {{ClientImpl.WebTargetImpl.request()}} which calls 
{{{}clientCfg.getRequestContext().putAll(configProps){}}}, placing the property 
*directly at the top level* of the request context. {{getContextualProperty()}} 
then finds it correctly.

*Expected Behaviour:*

When {{set.content.type.for.empty.request}} is set to {{FALSE}} via 
{{{}Invocation.Builder.property(){}}}, the HTTP transport should honour the 
setting and omit the {{Content-Type}} header for non-GET requests with an empty 
entity body, consistent with the behaviour when the same property is set via 
{{Client.property()}} or {{{}WebTarget.property(){}}}.

*Affected versions:* Verified with CXF 3.1.18 and 3.5.5. Likely affects other 
maintained branches.

*Steps to reproduce:*

 
{{Client client = ClientBuilder.newClient();Invocation.Builder builder = 
client.target("http://example.com/api";).request();}}

{{builder.property("set.content.type.for.empty.request", "FALSE");// Issue a 
POST/DELETE with no entity body}}

{{// Observed: Content-Type header is still sent// Expected: Content-Type 
header is omitted}}

  was:
{{InvocationBuilderImpl.property()}} stores request properties in a nested map 
under the key {{jaxrs.filter.properties}} inside the WebClient request context. 
When a client calls:

 
{{builder.property("set.content.type.for.empty.request", "FALSE")}}
 
the value is stored inside that nested map, not at the top level of the request 
context.

However, {{Headers.setProtocolHeadersInConnection()}} retrieves the property 
via 
{{{}message.getContextualProperty("set.content.type.for.empty.request"){}}}, 
which builds a merged context cache from Bus → Service → Endpoint → Exchange → 
Message using shallow {{putAll()}} calls. The nested 
{{jaxrs.filter.properties}} map is present in the cache as an opaque {{Map}} 
value under that key, but its contents are never unpacked. Consequently, 
{{getContextualProperty()}} returns {{{}null{}}}, the 
{{set.content.type.for.empty.request}} configuration is silently ignored, and 
the {{Content-Type}} header is always added to non-GET requests with an empty 
entity body.

*Working scenario (for contrast):*

Setting the property at the {{Client}} or {{WebTarget}} level works correctly:

 
{{client.property("set.content.type.for.empty.request", "FALSE")// 
orwebTarget.property("set.content.type.for.empty.request", "FALSE")}}
 
This goes through {{ClientImpl.WebTargetImpl.request()}} which calls 
{{{}clientCfg.getRequestContext().putAll(configProps){}}}, placing the property 
*directly at the top level* of the request context. {{getContextualProperty()}} 
then finds it correctly.

*Expected Behaviour:*

When {{set.content.type.for.empty.request}} is set to {{FALSE}} via 
{{{}Invocation.Builder.property(){}}}, the HTTP transport should honour the 
setting and omit the {{Content-Type}} header for non-GET requests with an empty 
entity body, consistent with the behaviour when the same property is set via 
{{Client.property()}} or {{{}WebTarget.property(){}}}.

*Affected versions:* Verified with CXF 3.1.18 and 3.5.5. Likely affects other 
maintained branches.

*Steps to reproduce:*

 
{{Client client = ClientBuilder.newClient();Invocation.Builder builder = 
client.target("http://example.com/api";)                                   
.request();builder.property("set.content.type.for.empty.request", "FALSE");// 
Issue a POST/DELETE with no entity body// Observed: Content-Type header is 
still sent// Expected: Content-Type header is omitted}}


> Invocation.Builder.property() settings ignored by HTTP transport for 
> set.content.type.for.empty.request
> -------------------------------------------------------------------------------------------------------
>
>                 Key: CXF-9235
>                 URL: https://issues.apache.org/jira/browse/CXF-9235
>             Project: CXF
>          Issue Type: Bug
>            Reporter: Neena Jacob
>            Priority: Minor
>
> {{InvocationBuilderImpl.property()}} stores request properties in a nested 
> map under the key {{jaxrs.filter.properties}} inside the WebClient request 
> context. When a client calls:
>  
> {{builder.property("set.content.type.for.empty.request", "FALSE")}}
>  
> the value is stored inside that nested map, not at the top level of the 
> request context.
> However, {{Headers.setProtocolHeadersInConnection()}} retrieves the property 
> via 
> {{{}message.getContextualProperty("set.content.type.for.empty.request"){}}}, 
> which builds a merged context cache from Bus → Service → Endpoint → Exchange 
> → Message using shallow {{putAll()}} calls. The nested 
> {{jaxrs.filter.properties}} map is present in the cache as an opaque {{Map}} 
> value under that key, but its contents are never unpacked. Consequently, 
> {{getContextualProperty()}} returns {{{}null{}}}, the 
> {{set.content.type.for.empty.request}} configuration is silently ignored, and 
> the {{Content-Type}} header is always added to non-GET requests with an empty 
> entity body.
> *Working scenario (for contrast):*
> Setting the property at the {{Client}} or {{WebTarget}} level works correctly:
>  
> {{client.property("set.content.type.for.empty.request", "FALSE")// 
> orwebTarget.property("set.content.type.for.empty.request", "FALSE")}}
>  
> This goes through {{ClientImpl.WebTargetImpl.request()}} which calls 
> {{{}clientCfg.getRequestContext().putAll(configProps){}}}, placing the 
> property *directly at the top level* of the request context. 
> {{getContextualProperty()}} then finds it correctly.
> *Expected Behaviour:*
> When {{set.content.type.for.empty.request}} is set to {{FALSE}} via 
> {{{}Invocation.Builder.property(){}}}, the HTTP transport should honour the 
> setting and omit the {{Content-Type}} header for non-GET requests with an 
> empty entity body, consistent with the behaviour when the same property is 
> set via {{Client.property()}} or {{{}WebTarget.property(){}}}.
> *Affected versions:* Verified with CXF 3.1.18 and 3.5.5. Likely affects other 
> maintained branches.
> *Steps to reproduce:*
>  
> {{Client client = ClientBuilder.newClient();Invocation.Builder builder = 
> client.target("http://example.com/api";).request();}}
> {{builder.property("set.content.type.for.empty.request", "FALSE");// Issue a 
> POST/DELETE with no entity body}}
> {{// Observed: Content-Type header is still sent// Expected: Content-Type 
> header is omitted}}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to