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 383cfd02ed5 Make sure UriInfoImpl#getMatchedResourceTemplate 
incorporates application path if configured (#3060)
383cfd02ed5 is described below

commit 383cfd02ed539dc662cddd7d72f61f84780b083a
Author: Andriy Redko <[email protected]>
AuthorDate: Sat May 2 10:52:15 2026 -0400

    Make sure UriInfoImpl#getMatchedResourceTemplate incorporates application 
path if configured (#3060)
---
 .../apache/cxf/jaxrs/JAXRSServerFactoryBean.java   |  1 +
 .../org/apache/cxf/jaxrs/impl/UriInfoImpl.java     | 27 ++++++++++++++++++----
 .../apache/cxf/jaxrs/model/ApplicationInfo.java    | 10 ++++++++
 .../apache/cxf/jaxrs/model/ClassResourceInfo.java  | 10 ++++++++
 .../org/apache/cxf/jaxrs/utils/ResourceUtils.java  |  2 +-
 .../org/apache/cxf/jaxrs/impl/UriInfoImplTest.java | 17 ++++++++++++--
 .../jaxrs/JAXRSClientServerNonSpringBookTest.java  |  2 +-
 7 files changed, 60 insertions(+), 9 deletions(-)

diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java
 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java
index db19519ea5c..245cb381f7d 100644
--- 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java
+++ 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java
@@ -104,6 +104,7 @@ public class JAXRSServerFactoryBean extends 
AbstractJAXRSFactoryBean {
             Set<String> clsNameBindings = new LinkedHashSet<>(appNameBindings);
             clsNameBindings.addAll(AnnotationUtils.getNameBindings(bus, 
cri.getServiceClass()));
             cri.setNameBindings(clsNameBindings);
+            cri.setApplicationInfo(provider);
         }
     }
 
diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java
index b4e99347ccc..0bf450c206a 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/UriInfoImpl.java
@@ -27,11 +27,13 @@ import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
 
+import jakarta.ws.rs.ApplicationPath;
 import jakarta.ws.rs.core.MultivaluedMap;
 import jakarta.ws.rs.core.PathSegment;
 import jakarta.ws.rs.core.UriBuilder;
 import jakarta.ws.rs.core.UriInfo;
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
 import org.apache.cxf.jaxrs.model.MethodInvocationInfo;
 import org.apache.cxf.jaxrs.model.OperationResourceInfo;
 import org.apache.cxf.jaxrs.model.OperationResourceInfoStack;
@@ -41,6 +43,8 @@ import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
 
+import io.micrometer.common.util.StringUtils;
+
 public class UriInfoImpl implements UriInfo {
     private static final Logger LOG = LogUtils.getL7dLogger(UriInfoImpl.class);
     private static final String CASE_INSENSITIVE_QUERIES = 
"org.apache.cxf.http.case_insensitive_queries";
@@ -246,10 +250,15 @@ public class UriInfoImpl implements UriInfo {
     @Override
     public String getMatchedResourceTemplate() {
         if (stack != null) {
+            ApplicationPath applicationPath = null;
             final List<URITemplate> templates = new LinkedList<>();
             for (MethodInvocationInfo invocation : stack) {
-                OperationResourceInfo ori = invocation.getMethodInfo();
-                final URITemplate classUriTemplate = 
ori.getClassResourceInfo().getURITemplate();
+                final OperationResourceInfo ori = invocation.getMethodInfo();
+                final ClassResourceInfo cri = ori.getClassResourceInfo();
+                if (cri.getApplicationInfo() != null && applicationPath == 
null) {
+                    applicationPath = 
cri.getApplicationInfo().getApplicationPath();
+                }
+                final URITemplate classUriTemplate = cri.getURITemplate();
                 if (classUriTemplate != null) {
                     templates.add(classUriTemplate);
                 }
@@ -257,9 +266,17 @@ public class UriInfoImpl implements UriInfo {
             }
             
             if (!templates.isEmpty()) {
-                UriBuilder builder = 
UriBuilder.fromPath(templates.get(0).getValue());
-                for (int i = 1; i < templates.size(); ++i) {
-                    builder = builder.path(templates.get(i).getValue());
+                UriBuilder builder = null;
+                if (applicationPath != null && 
!StringUtils.isBlank(applicationPath.value())) {
+                    builder = UriBuilder.fromPath(applicationPath.value());
+                    for (int i = 0; i < templates.size(); ++i) {
+                        builder = builder.path(templates.get(i).getValue());
+                    }
+                } else {
+                    builder = UriBuilder.fromPath(templates.get(0).getValue());
+                    for (int i = 1; i < templates.size(); ++i) {
+                        builder = builder.path(templates.get(i).getValue());
+                    }
                 }
                 return builder.toTemplate();
             }
diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ApplicationInfo.java
 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ApplicationInfo.java
index 26242836480..7ae9ec0c050 100644
--- 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ApplicationInfo.java
+++ 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ApplicationInfo.java
@@ -22,12 +22,16 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import jakarta.ws.rs.ApplicationPath;
 import jakarta.ws.rs.core.Application;
 import org.apache.cxf.Bus;
 import org.apache.cxf.jaxrs.impl.tl.ThreadLocalProxy;
+import org.apache.cxf.jaxrs.utils.ResourceUtils;
 
 public class ApplicationInfo extends ProviderInfo<Application> {
     private Map<String, Object> overridingProps = Collections.emptyMap();
+    private final ApplicationPath applicationPath;
+    
     public ApplicationInfo(Application provider, Bus bus) {
         this(provider, null, bus);
     }
@@ -35,6 +39,7 @@ public class ApplicationInfo extends 
ProviderInfo<Application> {
                         Map<Class<?>, ThreadLocalProxy<?>> constructorProxies,
                         Bus bus) {
         super(provider, constructorProxies, bus, true);
+        this.applicationPath = 
ResourceUtils.locateApplicationPath(provider.getClass());
     }
 
     public Map<String, Object> getProperties() {
@@ -46,7 +51,12 @@ public class ApplicationInfo extends 
ProviderInfo<Application> {
         props.putAll(overridingProps);
         return props;
     }
+
     public void setOverridingProps(Map<String, Object> overridingProps) {
         this.overridingProps = overridingProps;
     }
+
+    public ApplicationPath getApplicationPath() {
+        return applicationPath;
+    }
 }
diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ClassResourceInfo.java
 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ClassResourceInfo.java
index 1903501415e..427c90e80c5 100644
--- 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ClassResourceInfo.java
+++ 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ClassResourceInfo.java
@@ -62,6 +62,8 @@ public class ClassResourceInfo extends BeanResourceInfo {
     private Set<String> nameBindings = Collections.emptySet();
     private ClassResourceInfo parent;
     private Set<String> injectedSubInstances = new HashSet<>();
+    private ApplicationInfo applicationInfo;
+
     public ClassResourceInfo(ClassResourceInfo cri) {
         super(cri.getBus());
         if (cri.isCreatedFromModel() && 
!InjectionUtils.isConcreteClass(cri.getServiceClass())) {
@@ -362,4 +364,12 @@ public class ClassResourceInfo extends BeanResourceInfo {
             }
         }
     }
+    
+    public ApplicationInfo getApplicationInfo() {
+        return applicationInfo;
+    }
+    
+    public void setApplicationInfo(ApplicationInfo applicationInfo) {
+        this.applicationInfo = applicationInfo;
+    }
 }
diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
index 1355d1a1b44..5b29d15b132 100644
--- 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
+++ 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
@@ -1033,7 +1033,7 @@ public final class ResourceUtils {
 
     public static ApplicationPath locateApplicationPath(Class<?> appClass) {
         ApplicationPath appPath = 
appClass.getAnnotation(ApplicationPath.class);
-        if (appPath == null && appClass.getSuperclass() != Application.class) {
+        if (appPath == null && appClass.getSuperclass() != null && 
appClass.getSuperclass() != Application.class) {
             return locateApplicationPath(appClass.getSuperclass());
         }
         return appPath;
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
index 4b893a3dcf1..df92295f3c5 100644
--- 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
+++ 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/UriInfoImplTest.java
@@ -24,12 +24,15 @@ import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
 
+import jakarta.ws.rs.ApplicationPath;
 import jakarta.ws.rs.GET;
 import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Application;
 import jakarta.ws.rs.core.MultivaluedMap;
 import jakarta.ws.rs.core.PathSegment;
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.core.UriInfo;
+import org.apache.cxf.jaxrs.model.ApplicationInfo;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
 import org.apache.cxf.jaxrs.model.MethodInvocationInfo;
 import org.apache.cxf.jaxrs.model.OperationResourceInfo;
@@ -577,9 +580,14 @@ public class UriInfoImplTest {
 
     @Test
     public void 
testGetMatchedResourceTemplateIncludesApplicationPathAndTemplateVariables() 
throws Exception {
+        @ApplicationPath("/app") 
+        class App extends Application {
+        }
+
         Message m = mockMessage("http://localhost:8080/app";, "/foo/one/abc");
         OperationResourceInfoStack oriStack = new OperationResourceInfoStack();
         ClassResourceInfo cri = getCri(RootResource.class, true);
+        cri.setApplicationInfo(new ApplicationInfo(new App(), null));
         OperationResourceInfo ori = getOri(cri, "getTemplate");
 
         MethodInvocationInfo miInfo = new MethodInvocationInfo(ori, 
RootResource.class, new ArrayList<String>());
@@ -587,7 +595,7 @@ public class UriInfoImplTest {
         m.put(OperationResourceInfoStack.class, oriStack);
 
         UriInfoImpl u = new UriInfoImpl(m);
-        assertEquals("/foo/one/{name:[a-zA-Z][a-zA-Z_0-9]*}", 
u.getMatchedResourceTemplate());
+        assertEquals("/app/foo/one/{name:[a-zA-Z][a-zA-Z_0-9]*}", 
u.getMatchedResourceTemplate());
     }
 
     @Test
@@ -607,10 +615,15 @@ public class UriInfoImplTest {
 
     @Test
     public void 
testGetMatchedResourceTemplateIgnoresPathBeforeApplicationPath() throws 
Exception {
+        @ApplicationPath("/service") 
+        class App extends Application {
+        }
+
         Message m = mockMessage("http://localhost:8080/context/service";, 
"/foo/bar");
 
         OperationResourceInfoStack oriStack = new OperationResourceInfoStack();
         ClassResourceInfo cri = getCri(RootResource.class, true);
+        cri.setApplicationInfo(new ApplicationInfo(new App(), null));
         OperationResourceInfo ori = getOri(cri, "getSubMethod");
 
         MethodInvocationInfo miInfo = new MethodInvocationInfo(ori, 
RootResource.class, new ArrayList<String>());
@@ -618,7 +631,7 @@ public class UriInfoImplTest {
         m.put(OperationResourceInfoStack.class, oriStack);
 
         UriInfoImpl u = new UriInfoImpl(m);
-        assertEquals("/foo/bar", u.getMatchedResourceTemplate());
+        assertEquals("/service/foo/bar", u.getMatchedResourceTemplate());
     }
 
     @Test
diff --git 
a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java
 
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java
index cd19a68b979..b7b207a4ad7 100644
--- 
a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java
+++ 
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java
@@ -210,7 +210,7 @@ public class JAXRSClientServerNonSpringBookTest extends 
AbstractBusClientServerT
         WebClient wc = WebClient.create("http://localhost:"; + PORT
                                         + 
"/application6/the%20books2/bookstore2/book%20template/abc");
         assertThat(wc.accept("*/*").get(String.class),
-            
equalTo("/bookstore2/book%20template/{name:[a-zA-Z][a-zA-Z_0-9]*}"));
+            
equalTo("/the%20books2/bookstore2/book%20template/{name:[a-zA-Z][a-zA-Z_0-9]*}"));
     }
 
     @SafeVarargs

Reply via email to