This is an automated email from the ASF dual-hosted git repository.
ffang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/main by this push:
new 4fdf9fe2ea7 fix Invocation.Builder.property() not visible to HTTP
transport (#3375)
4fdf9fe2ea7 is described below
commit 4fdf9fe2ea7329df785bc9a4c8d1e2e555414eb5
Author: Neena P Jacob <[email protected]>
AuthorDate: Tue Aug 18 19:55:41 2026 +0530
fix Invocation.Builder.property() not visible to HTTP transport (#3375)
---
.../jaxrs/client/spec/InvocationBuilderImpl.java | 4 ++
.../client/spec/InvocationBuilderImplTest.java | 61 ++++++++++++++++++++++
2 files changed, 65 insertions(+)
diff --git
a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/InvocationBuilderImpl.java
b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/InvocationBuilderImpl.java
index 25c85abd825..5b062151f88 100644
---
a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/InvocationBuilderImpl.java
+++
b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/spec/InvocationBuilderImpl.java
@@ -288,8 +288,12 @@ public class InvocationBuilderImpl implements
Invocation.Builder {
}
if (value == null) {
filterProps.remove(name);
+ contextProps.remove(name);
} else {
filterProps.put(name, value);
+ // CXF-9235: also write to the top-level context so that the
transport layer
+ // can find the property via Message.getContextualProperty()
+ contextProps.put(name, value);
}
return this;
}
diff --git
a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spec/InvocationBuilderImplTest.java
b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spec/InvocationBuilderImplTest.java
index 9569bfeddf1..6dcba9a8371 100644
---
a/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spec/InvocationBuilderImplTest.java
+++
b/rt/rs/client/src/test/java/org/apache/cxf/jaxrs/client/spec/InvocationBuilderImplTest.java
@@ -19,6 +19,7 @@
package org.apache.cxf.jaxrs.client.spec;
import java.io.IOException;
+import java.util.Map;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
@@ -28,15 +29,21 @@ import jakarta.ws.rs.client.Invocation.Builder;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.transport.http.Headers;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class InvocationBuilderImplTest {
+ private static final String FILTER_PROPS_KEY = "jaxrs.filter.properties";
+
public static class TestFilter implements ClientRequestFilter {
/** {@inheritDoc}*/
@@ -83,4 +90,58 @@ public class InvocationBuilderImplTest {
response = builder.get();
assertEquals("", response.readEntity(String.class));
}
+
+ /**
+ * CXF-9235: Invocation.Builder.property() must write the property value
into BOTH:
+ *
+ * (a) the nested "jaxrs.filter.properties" sub-map inside the
ClientConfiguration
+ * request context — this is what context.getProperty() reads inside a
+ * ClientRequestFilter (via MessagePropertyHolder /
Exchange.get(PROPERTY_KEY)).
+ *
+ * (b) the flat top-level ClientConfiguration request context — this is
what the
+ * HTTP transport reads via Message.getContextualProperty() in
+ * Headers.setProtocolHeadersInConnection().
+ *
+ * Before the fix only (a) was written. The transport (b) path was
silently missing,
+ * meaning a property like "set.content.type.for.empty.request" set on the
+ * Invocation.Builder had no effect on the conduit.
+ */
+ @Test
+ public void testPropertyWrittenToBothFilterPropsAndFlatContext() {
+ Client client = ClientBuilder.newClient().register(TestFilter.class);
+ Builder builder =
client.target("http://localhost:8080/notReal").request();
+
+ // ---- set ----
+ builder.property(Headers.SET_EMPTY_REQUEST_CT_PROPERTY, Boolean.FALSE);
+
+ InvocationBuilderImpl builderImpl = (InvocationBuilderImpl) builder;
+ Map<String, Object> requestContext =
+
WebClient.getConfig(builderImpl.getWebClient()).getRequestContext();
+
+ // (a) Must be in the nested filterProps sub-map that a
ClientRequestFilter reads.
+ // This path was already written before the fix; we guard it stays
working.
+ Map<String, Object> filterProps =
+ CastUtils.cast((Map<?, ?>)
requestContext.get(FILTER_PROPS_KEY));
+ assertTrue("jaxrs.filter.properties sub-map must exist after
Builder.property()",
+ filterProps != null &&
filterProps.containsKey(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));
+ assertEquals("Value in filterProps must match what was set",
+ Boolean.FALSE,
filterProps.get(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));
+
+ // (b) Must also be present flat in the top-level context — the path
the HTTP
+ // transport reads via Message.getContextualProperty(). This was
the bug in
+ // CXF-9235: only (a) was written, so the transport never saw the
property.
+ assertEquals("Flat request context must contain the property for the
transport layer (CXF-9235)",
+ Boolean.FALSE,
requestContext.get(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));
+
+ // ---- remove (null value) ----
+ builder.property(Headers.SET_EMPTY_REQUEST_CT_PROPERTY, null);
+
+ // (a) removed from filterProps
+ assertNull("Null value must remove property from filterProps sub-map",
+ filterProps.get(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));
+
+ // (b) removed from flat context
+ assertFalse("Null value must remove property from the flat transport
context (CXF-9235)",
+
requestContext.containsKey(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));
+ }
}