You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2026/10/16 11:22:17 UTC

(cxf) branch main updated: CXF-6301: Deliver faults marked as partial responses to async callbacks (#3591)

This is an automated email from the ASF dual-hosted git repository.

coheigea 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 df01f78e0ba CXF-6301: Deliver faults marked as partial responses to async callbacks (#3591)
df01f78e0ba is described below

commit df01f78e0bae55026647835c1d8ceaf6bcbcd296
Author: Colm O hEigeartaigh <co...@users.noreply.github.com>
AuthorDate: Fri Oct 16 12:22:11 2026 +0100

    CXF-6301: Deliver faults marked as partial responses to async callbacks (#3591)
---
 .../java/org/apache/cxf/endpoint/ClientImpl.java   |   3 +-
 .../cxf/jaxws/dispatch/DispatchAsyncFaultTest.java | 129 +++++++++++++++++++++
 .../cxf/jaxws/dispatch/Soap12FaultNoRelatesTo.xml  |  40 +++++++
 3 files changed, 171 insertions(+), 1 deletion(-)

diff --git a/core/src/main/java/org/apache/cxf/endpoint/ClientImpl.java b/core/src/main/java/org/apache/cxf/endpoint/ClientImpl.java
index 35803e1c4f2..aaeb3c1e384 100644
--- a/core/src/main/java/org/apache/cxf/endpoint/ClientImpl.java
+++ b/core/src/main/java/org/apache/cxf/endpoint/ClientImpl.java
@@ -933,7 +933,8 @@ public class ClientImpl
             }
 
             callback = message.getExchange().get(ClientCallback.class);
-            if (callback == null || isPartialResponse(message)) {
+            if (callback == null
+                || (isPartialResponse(message) && message.getContent(Exception.class) == null)) {
                 return;
             }
 
diff --git a/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchAsyncFaultTest.java b/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchAsyncFaultTest.java
new file mode 100644
index 00000000000..3ff9db53875
--- /dev/null
+++ b/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/DispatchAsyncFaultTest.java
@@ -0,0 +1,129 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.jaxws.dispatch;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.namespace.QName;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+
+import org.w3c.dom.Document;
+
+import jakarta.xml.ws.Dispatch;
+import jakarta.xml.ws.Response;
+import jakarta.xml.ws.Service;
+import jakarta.xml.ws.soap.AddressingFeature;
+import jakarta.xml.ws.soap.SOAPBinding;
+import jakarta.xml.ws.soap.SOAPFaultException;
+import org.apache.cxf.binding.soap.SoapFault;
+import org.apache.cxf.jaxws.AbstractJaxWsTest;
+import org.apache.cxf.jaxws.MessageReplayObserver;
+import org.apache.cxf.jaxws.ServiceImpl;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.cxf.transport.Destination;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * CXF-6301: a SOAP 1.2 fault carrying WS-Addressing headers but no wsa:RelatesTo must be
+ * delivered to an AsyncHandler, as it already is for a synchronous invocation.
+ */
+public class DispatchAsyncFaultTest extends AbstractJaxWsTest {
+    private static final QName SERVICE_NAME = new QName("http://cxf.apache.org/test/dispatch", "DispatchTest");
+
+    private static final QName PORT_NAME = new QName("http://cxf.apache.org/test/dispatch", "DispatchPort");
+
+    private static final String ADDRESS = "http://localhost:9121/SoapContext/DispatchPort";
+
+    private static final String REQ_RESOURCE = "/org/apache/cxf/jaxws/dispatch/OperationRequest.xml";
+
+    private static final String FAULT_RESOURCE = "/org/apache/cxf/jaxws/dispatch/Soap12FaultNoRelatesTo.xml";
+
+    private Destination d;
+
+    @Before
+    public void setUp() throws Exception {
+        EndpointInfo ei = new EndpointInfo(null, "http://schemas.xmlsoap.org/soap/http");
+        ei.setAddress(ADDRESS);
+
+        d = localTransport.getDestination(ei, bus);
+        d.setMessageObserver(new MessageReplayObserver(FAULT_RESOURCE));
+    }
+
+    @Test
+    public void testSyncFaultWithoutRelatesTo() throws Exception {
+        Dispatch<Source> disp = createDispatch();
+        try {
+            disp.invoke(createRequest());
+            fail("Expected SOAPFaultException");
+        } catch (SOAPFaultException ex) {
+            assertEquals("NotSupported", ex.getMessage());
+        }
+    }
+
+    @Test
+    public void testAsyncHandlerFaultWithoutRelatesTo() throws Exception {
+        Dispatch<Source> disp = createDispatch();
+        CompletableFuture<Response<Source>> handled = new CompletableFuture<>();
+        disp.invokeAsync(createRequest(), handled::complete);
+
+        Response<Source> response = handled.get(30, TimeUnit.SECONDS);
+        try {
+            response.get();
+            fail("Expected ExecutionException");
+        } catch (ExecutionException ex) {
+            assertTrue(ex.getCause() instanceof SoapFault);
+            assertEquals("NotSupported", ex.getCause().getMessage());
+        }
+    }
+
+    @Test
+    public void testAsyncResponseFaultWithoutRelatesTo() throws Exception {
+        Dispatch<Source> disp = createDispatch();
+        Response<Source> response = disp.invokeAsync(createRequest());
+        try {
+            response.get(30, TimeUnit.SECONDS);
+            fail("Expected ExecutionException");
+        } catch (ExecutionException ex) {
+            assertTrue(ex.getCause() instanceof SOAPFaultException);
+            assertEquals("NotSupported", ex.getCause().getMessage());
+        }
+    }
+
+    private Dispatch<Source> createDispatch() {
+        ServiceImpl service = new ServiceImpl(getBus(), null, SERVICE_NAME, null, new AddressingFeature());
+        service.addPort(PORT_NAME, SOAPBinding.SOAP12HTTP_BINDING, ADDRESS);
+        return service.createDispatch(PORT_NAME, Source.class, Service.Mode.PAYLOAD);
+    }
+
+    private Source createRequest() throws Exception {
+        Document doc = StaxUtils.read(getResourceAsStream(REQ_RESOURCE));
+        return new DOMSource(doc);
+    }
+}
diff --git a/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/Soap12FaultNoRelatesTo.xml b/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/Soap12FaultNoRelatesTo.xml
new file mode 100644
index 00000000000..fc4078e6339
--- /dev/null
+++ b/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/dispatch/Soap12FaultNoRelatesTo.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<!-- SOAP 1.2 fault with WS-Addressing headers but no wsa:RelatesTo (CXF-6301) -->
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
+    <SOAP-ENV:Header>
+        <Action xmlns="http://www.w3.org/2005/08/addressing">urn://Ocpp/cp/2012/06/:ChargePointService::Fault</Action>
+        <MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:a2eea7dd-1d3c-437c-870e-2dff0a63d44d</MessageID>
+    </SOAP-ENV:Header>
+    <SOAP-ENV:Body>
+        <SOAP-ENV:Fault>
+            <SOAP-ENV:Code>
+                <SOAP-ENV:Value>SOAP-ENV:Receiver</SOAP-ENV:Value>
+            </SOAP-ENV:Code>
+            <SOAP-ENV:Reason>
+                <SOAP-ENV:Text>NotSupported</SOAP-ENV:Text>
+            </SOAP-ENV:Reason>
+            <detail>SOAP-ENV:NotSupported</detail>
+        </SOAP-ENV:Fault>
+    </SOAP-ENV:Body>
+</SOAP-ENV:Envelope>