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