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/14 08:46:04 UTC

(cxf) 01/01: CXF-7330: Require all type variable bounds to match when selecting providers

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

coheigea pushed a commit to branch coheigea/CXF-7330
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit e035dc1c1f2f9f2b14f0d3dda413db66d795b38d
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Wed Oct 14 09:45:43 2026 +0100

    CXF-7330: Require all type variable bounds to match when selecting providers
---
 .../apache/cxf/jaxrs/provider/ProviderFactory.java |  7 ++---
 .../cxf/jaxrs/provider/ProviderFactoryTest.java    | 31 +++++++++++++++++++++-
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
index 18f0a9e1098..e89b66777db 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
@@ -393,11 +393,12 @@ public abstract class ProviderFactory {
                     if (arg instanceof TypeVariable) {
                         TypeVariable<?> var = (TypeVariable<?>) arg;
                         Type[] bounds = var.getBounds();
-                        boolean isResolved = false;
+                        // all the bounds must match, e.g. T extends Throwable & SomeInterface
+                        boolean isResolved = true;
                         for (Type bound : bounds) {
                             Class<?> cls = InjectionUtils.getRawType(bound);
-                            if (cls != null && (cls == Object.class || cls.isAssignableFrom(expectedType))) {
-                                isResolved = true;
+                            if (cls == null || (cls != Object.class && !cls.isAssignableFrom(expectedType))) {
+                                isResolved = false;
                                 break;
                             }
                         }
diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryTest.java b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryTest.java
index da351ce764d..db993f2091d 100644
--- a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryTest.java
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryTest.java
@@ -831,6 +831,16 @@ public class ProviderFactoryTest {
         assertNull(mapper2);
     }
 
+    @Test
+    public void testExceptionMapperWithMultipleBounds() {
+        ServerProviderFactory pf = ServerProviderFactory.getInstance();
+        FaultInfoExceptionMapper<?> faultInfoMapper = new FaultInfoExceptionMapper<>();
+        pf.registerUserProvider(faultInfoMapper);
+        assertSame(faultInfoMapper,
+            pf.createExceptionMapper(FaultInfoException.class, new MessageImpl()));
+        assertNull(pf.createExceptionMapper(RuntimeException.class, new MessageImpl()));
+    }
+
     @Test
     public void testRegisterCustomResolver() throws Exception {
         ProviderFactory pf = ServerProviderFactory.getInstance();
@@ -1616,4 +1626,23 @@ public class ProviderFactoryTest {
         }
     }
 
-}
\ No newline at end of file
+    public interface FaultInfo {
+        String getFaultInfo();
+    }
+
+    public static class FaultInfoException extends RuntimeException implements FaultInfo {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public String getFaultInfo() {
+            return "fault";
+        }
+    }
+
+    public static class FaultInfoExceptionMapper<T extends Throwable & FaultInfo> implements ExceptionMapper<T> {
+        @Override
+        public Response toResponse(T exception) {
+            return Response.serverError().entity(exception.getFaultInfo()).build();
+        }
+    }
+}