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

reta 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 705978657e CXF-9076: Exception message is not unmarshalled with JDK17+ 
(#2137)
705978657e is described below

commit 705978657e2dcf7aef61c1aab0a7f1108dee2980
Author: Andriy Redko <[email protected]>
AuthorDate: Sun Nov 10 11:59:44 2024 -0500

    CXF-9076: Exception message is not unmarshalled with JDK17+ (#2137)
---
 .../cxf/interceptor/ClientFaultConverter.java      | 25 ++++++++--
 .../systest/jaxws/ClientServerExceptionServer.java | 55 ++++++++++++++++++++++
 .../systest/jaxws/ClientServerExceptionTest.java   | 54 +++++++++++++++++++++
 .../apache/cxf/systest/jaxws/ExceptionService.java | 27 +++++++++++
 4 files changed, 157 insertions(+), 4 deletions(-)

diff --git 
a/core/src/main/java/org/apache/cxf/interceptor/ClientFaultConverter.java 
b/core/src/main/java/org/apache/cxf/interceptor/ClientFaultConverter.java
index e6b9f97705..c2c1f9c365 100644
--- a/core/src/main/java/org/apache/cxf/interceptor/ClientFaultConverter.java
+++ b/core/src/main/java/org/apache/cxf/interceptor/ClientFaultConverter.java
@@ -191,17 +191,34 @@ public class ClientFaultConverter extends 
AbstractInDatabindingInterceptor {
                 LogUtils.log(LOG, Level.INFO, 
"EXCEPTION_WHILE_CREATING_EXCEPTION", e1, e1.getMessage());
             }
         } else {
-            if (fault.getMessage() != null) {
+            Exception ex = (Exception)e; 
+            final String message = fault.getMessage();
+            if (message != null) {
                 Field f;
                 try {
                     f = Throwable.class.getDeclaredField("detailMessage");
                     ReflectionUtil.setAccessible(f);
-                    f.set(e, fault.getMessage());
+                    f.set(ex, fault.getMessage());
                 } catch (Exception e1) {
-                    //ignore
+                    try {
+                        // Fallback, try to clone the exception instead of 
accessing the detailMessage over reflection
+                        final Constructor<? extends Object> constructor = 
ReflectionUtil.getConstructor(ex.getClass(),
+                            String.class, Throwable.class); /* String message, 
Throwable cause */
+
+                        if (constructor != null) {
+                            final Exception clone = (Exception) 
constructor.newInstance(message, ex.getCause());
+                            clone.setStackTrace(ex.getStackTrace());
+                            if (ex.getSuppressed().length > 0) {
+                                
Arrays.stream(ex.getSuppressed()).forEach(clone::addSuppressed);
+                            }
+                            ex = clone;
+                        }
+                    } catch (Exception e2) {
+                        /* nothing to do */
+                    }
                 }
             }
-            msg.setContent(Exception.class, e);
+            msg.setContent(Exception.class, ex);
         }
     }
 
diff --git 
a/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerExceptionServer.java
 
b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerExceptionServer.java
new file mode 100644
index 0000000000..06ad7e98f0
--- /dev/null
+++ 
b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerExceptionServer.java
@@ -0,0 +1,55 @@
+/**
+ * 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.systest.jaxws;
+
+import jakarta.jws.WebService;
+import jakarta.xml.ws.Endpoint;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+
+public class ClientServerExceptionServer extends AbstractBusTestServerBase {
+    static final String PORT = allocatePort(ClientServerExceptionServer.class);
+
+    @WebService(endpointInterface = 
"org.apache.cxf.systest.jaxws.ExceptionService",
+        serviceName = "ExceptionService", targetNamespace = 
"http://cxf.apache.org/";)
+    static class ExceptionServiceImpl implements ExceptionService {
+        @Override
+        public String saySomething(String text) throws 
IllegalArgumentException {
+            throw new IllegalArgumentException("Simulated!");
+        }
+    }
+
+    protected void run() {
+        Object implementor = new ExceptionServiceImpl();
+        String address = "http://localhost:"; + PORT + "/ExceptionService";
+        Endpoint.publish(address, implementor);
+    }
+
+    public static void main(String[] args) {
+        try {
+            ClientServerExceptionServer s = new ClientServerExceptionServer();
+            s.start();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            System.exit(-1);
+        } finally {
+            System.out.println("done!");
+        }
+    }
+}
diff --git 
a/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerExceptionTest.java
 
b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerExceptionTest.java
new file mode 100644
index 0000000000..2e74489026
--- /dev/null
+++ 
b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerExceptionTest.java
@@ -0,0 +1,54 @@
+/**
+ * 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.systest.jaxws;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+
+import jakarta.xml.ws.Service;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+public class ClientServerExceptionTest extends AbstractBusClientServerTestBase 
{
+    @BeforeClass
+    public static void startServers() throws Exception {
+        assertTrue("server did not launch correctly", 
launchServer(ClientServerExceptionServer.class, true));
+    }
+
+    @Test
+    public void exceptionMessageIsPreserved() throws MalformedURLException {
+        URL wsdlURL = new URL("http://localhost:"; + 
ClientServerExceptionServer.PORT + "/ExceptionService?wsdl");
+        QName qname = new QName("http://cxf.apache.org/";, "ExceptionService");
+        Service service = Service.create(wsdlURL, qname);
+        ExceptionService port = service.getPort(ExceptionService.class);
+
+        final IllegalArgumentException ex = 
assertThrows(IllegalArgumentException.class,
+            () -> port.saySomething("Hello World!"));
+        assertEquals("Simulated!", ex.getMessage());
+    }
+}
diff --git 
a/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ExceptionService.java
 
b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ExceptionService.java
new file mode 100644
index 0000000000..ac2d87083f
--- /dev/null
+++ 
b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ExceptionService.java
@@ -0,0 +1,27 @@
+/**
+ * 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.systest.jaxws;
+
+import jakarta.jws.WebService;
+
+@WebService
+interface ExceptionService {
+    String saySomething(String text) throws IllegalArgumentException;
+}

Reply via email to