You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ff...@apache.org on 2026/08/18 14:25:46 UTC
(cxf) branch main updated: fix Invocation.Builder.property() not visible to HTTP transport (#3375)
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 <ne...@ibm.com>
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));
+ }
}