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 e6229afc8c CXF-9076: Exception message is not unmarshalled with JDK17+ 
(limit the fix to JDK standard library exceptions) (#2148)
e6229afc8c is described below

commit e6229afc8c15fe46b2c64116e76fea794af03f98
Author: Andriy Redko <[email protected]>
AuthorDate: Sun Nov 17 11:39:54 2024 -0500

    CXF-9076: Exception message is not unmarshalled with JDK17+ (limit the fix 
to JDK standard library exceptions) (#2148)
---
 .../cxf/interceptor/ClientFaultConverter.java      | 54 +++++++++++++++-------
 .../systest/jaxws/ClientServerExceptionServer.java |  5 ++
 .../systest/jaxws/ClientServerExceptionTest.java   | 20 ++++++--
 .../apache/cxf/systest/jaxws/ExceptionService.java |  1 +
 .../{ExceptionService.java => SayException.java}   | 19 ++++++--
 5 files changed, 76 insertions(+), 23 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 c2c1f9c365..c270f4d920 100644
--- a/core/src/main/java/org/apache/cxf/interceptor/ClientFaultConverter.java
+++ b/core/src/main/java/org/apache/cxf/interceptor/ClientFaultConverter.java
@@ -200,21 +200,8 @@ public class ClientFaultConverter extends 
AbstractInDatabindingInterceptor {
                     ReflectionUtil.setAccessible(f);
                     f.set(ex, fault.getMessage());
                 } catch (Exception e1) {
-                    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 */
+                    if (isJdkException(ex.getClass().getPackageName())) {
+                        ex = cloneJdkException(ex, message);
                     }
                 }
             }
@@ -222,6 +209,37 @@ public class ClientFaultConverter extends 
AbstractInDatabindingInterceptor {
         }
     }
 
+    private static Exception cloneJdkException(Exception ex, final String 
message) {
+        try {
+            // Fallback, try to clone the exception instead of accessing the 
detailMessage 
+            // over reflection
+            Constructor<? extends Object> constructor = 
ReflectionUtil.getConstructor(
+                ex.getClass(), String.class, Throwable.class); /* String 
message, Throwable cause */
+   
+            Exception clone = null;
+            if (constructor != null) {
+                clone = (Exception) constructor.newInstance(message, 
ex.getCause());
+            } else {
+                constructor = ReflectionUtil.getConstructor(ex.getClass(), 
String.class); /* String message */
+                if (constructor != null) {
+                    clone = (Exception) constructor.newInstance(message);
+                    clone.initCause(ex.getCause());
+                }
+            }
+
+            if (clone != null) {
+                clone.setStackTrace(ex.getStackTrace());
+                if (ex.getSuppressed().length > 0) {
+                    
Arrays.stream(ex.getSuppressed()).forEach(clone::addSuppressed);
+                }
+                return clone;
+            }
+        } catch (Exception e2) {
+            /* nothing to do */
+        }
+        return ex;
+    }
+
     private Constructor<?> getConstructor(Class<?> faultClass, Object e) 
throws NoSuchMethodException {
         Class<?> beanClass = e.getClass();
         Constructor<?>[] cons = faultClass.getConstructors();
@@ -300,7 +318,7 @@ public class ClientFaultConverter extends 
AbstractInDatabindingInterceptor {
         Throwable res = null;
         if (firstLine.indexOf(':') != -1) {
             String cn = firstLine.substring(0, firstLine.indexOf(':')).trim();
-            if (cn.startsWith("java.lang")) {
+            if (isJdkException(cn)) {
                 try {
                     res = 
(Throwable)Class.forName(cn).getConstructor(String.class)
                             
.newInstance(firstLine.substring(firstLine.indexOf(':') + 2));
@@ -327,6 +345,10 @@ public class ClientFaultConverter extends 
AbstractInDatabindingInterceptor {
         return res;
     }
 
+    private static boolean isJdkException(String pkg) {
+        return pkg.startsWith("java.lang");
+    }
+
     private static StackTraceElement parseStackTrackLine(String oneLine) {
         StringTokenizer stInner = new StringTokenizer(oneLine, "!");
         return new StackTraceElement(stInner.nextToken(), stInner.nextToken(),
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
index 06ad7e98f0..2cb2d371a6 100644
--- 
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
@@ -33,6 +33,11 @@ public class ClientServerExceptionServer extends 
AbstractBusTestServerBase {
         public String saySomething(String text) throws 
IllegalArgumentException {
             throw new IllegalArgumentException("Simulated!");
         }
+
+        @Override
+        public String sayNothing(String text) throws SayException {
+            throw new SayException("Simulated!", 100);
+        }
     }
 
     protected void run() {
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
index 2e74489026..73db4fcc54 100644
--- 
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
@@ -27,6 +27,7 @@ import javax.xml.namespace.QName;
 import jakarta.xml.ws.Service;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
 
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -35,20 +36,33 @@ import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
 public class ClientServerExceptionTest extends AbstractBusClientServerTestBase 
{
+    private ExceptionService port;
+
     @BeforeClass
     public static void startServers() throws Exception {
         assertTrue("server did not launch correctly", 
launchServer(ClientServerExceptionServer.class, true));
     }
 
-    @Test
-    public void exceptionMessageIsPreserved() throws MalformedURLException {
+    @Before
+    public void setUp() throws Exception {
         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);
+        port = service.getPort(ExceptionService.class);
+    }
 
+    @Test
+    public void exceptionMessageIsPreserved() throws MalformedURLException {
         final IllegalArgumentException ex = 
assertThrows(IllegalArgumentException.class,
             () -> port.saySomething("Hello World!"));
         assertEquals("Simulated!", ex.getMessage());
     }
+
+    @Test
+    public void exceptionCustomExceptionMessageIsPreserved() throws 
MalformedURLException {
+        final SayException ex = assertThrows(SayException.class,
+            () -> port.sayNothing("Hello World!"));
+        assertEquals("Simulated!", ex.getMessage());
+        assertEquals(100, ex.getCode());
+    }
 }
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
index ac2d87083f..6473b80972 100644
--- 
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
@@ -24,4 +24,5 @@ import jakarta.jws.WebService;
 @WebService
 interface ExceptionService {
     String saySomething(String text) throws IllegalArgumentException;
+    String sayNothing(String text) throws SayException;
 }
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/SayException.java
similarity index 70%
copy from 
systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ExceptionService.java
copy to 
systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/SayException.java
index ac2d87083f..0201400b0e 100644
--- 
a/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ExceptionService.java
+++ 
b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/SayException.java
@@ -19,9 +19,20 @@
 
 package org.apache.cxf.systest.jaxws;
 
-import jakarta.jws.WebService;
+public class SayException extends Exception {
+    private static final long serialVersionUID = 1L;
+    private final int code;
 
-@WebService
-interface ExceptionService {
-    String saySomething(String text) throws IllegalArgumentException;
+    public SayException() {
+        this(null, 0);
+    }
+
+    public SayException(final String message, final int code) {
+        super(message);
+        this.code = code;
+    }
+
+    public int getCode() {
+        return code;
+    }
 }

Reply via email to