This is an automated email from the ASF dual-hosted git repository. reta pushed a commit to branch 3.6.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 87eab88212ede935cfdb6724284c465c161b249d 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) (cherry picked from commit e6229afc8c15fe46b2c64116e76fea794af03f98) (cherry picked from commit d78b7b686ee03fba361099472bfde787cc33a9ed) --- .../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 a20db6bd12..ff80a8d940 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 @@ -34,6 +34,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 d0e8fe499c..6545d83709 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.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 fa2a525fa7..e2bf3e3c11 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 javax.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 fa2a525fa7..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 javax.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; + } }
