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


The following commit(s) were added to refs/heads/3.6.x-fixes by this push:
     new 82c2443e55e CXF-9211: [JAX-RS proxy clients] Use template URL instead 
of actual path values for JAX-RS micrometer metrics (#3100)
82c2443e55e is described below

commit 82c2443e55e2ec9117313b45e5f427a1a9583ab6
Author: Andriy Redko <[email protected]>
AuthorDate: Tue May 12 22:40:53 2026 -0400

    CXF-9211: [JAX-RS proxy clients] Use template URL instead of actual path 
values for JAX-RS micrometer metrics (#3100)
    
    (cherry picked from commit 99b0a407dc85f754de45185b5a2ab25d527ac277)
---
 .../org/apache/cxf/jaxrs/utils/JAXRSUtils.java     | 19 +++++++++-
 .../apache/cxf/jaxrs/client/ClientProxyImpl.java   |  2 +
 .../spring/boot/SpringJaxrsApplicationTest.java    | 44 +++++++++++++++++++++-
 .../systest/jaxrs/spring/boot/SpringJaxrsTest.java |  2 +-
 4 files changed, 63 insertions(+), 4 deletions(-)

diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
index f9075db21ca..3307d54b332 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
@@ -47,6 +47,7 @@ import java.util.TreeMap;
 import java.util.function.Supplier;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 import javax.ws.rs.ClientErrorException;
@@ -204,6 +205,7 @@ public final class JAXRSUtils {
             "java.util.concurrent.CompletionStage"
         ));
     private static final LazyLoadedClass DATA_SOURCE_CLASS = new 
LazyLoadedClass("javax.activation.DataSource");
+    private static final Pattern URI_SCHEME = 
Pattern.compile("^([a-zA-Z]{2,20}):\\/\\/", Pattern.CASE_INSENSITIVE);
 
     // Class to lazily call the ClassLoaderUtil.loadClass, but do it once
     // and cache the result.  Then use the class to create instances as needed.
@@ -2101,14 +2103,27 @@ public final class JAXRSUtils {
         String template = basePath;
         if (StringUtils.isEmpty(template)) {
             template = "/";
-        } else if (!template.startsWith("/")) {
+        } else if (!template.startsWith("/") && !hasScheme(template)) {
             template = "/" + template;
         }
         
         template = combineUriTemplates(template, classPathTemplate);
         return combineUriTemplates(template, methodPathTemplate);
     }
-    
+
+    /**
+     * Checks if the URI string is absolute with the scheme
+     * @param uriStr URI string
+     * @return "true" if the URI string is absolute with the scheme, "false" 
otherwise
+     */
+    private static boolean hasScheme(String uriStr) {
+        if (uriStr == null) {
+            return false;
+        } else {
+            return URI_SCHEME.matcher(uriStr).find();
+        }
+    }
+
     /**
      * Gets the URI template of the operation from its resource info
      * to assemble final URI template 
diff --git 
a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java 
b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java
index db7c84ecc3c..22dcdc4d494 100644
--- 
a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java
+++ 
b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java
@@ -89,6 +89,7 @@ import org.apache.cxf.jaxrs.model.ClassResourceInfo;
 import org.apache.cxf.jaxrs.model.OperationResourceInfo;
 import org.apache.cxf.jaxrs.model.Parameter;
 import org.apache.cxf.jaxrs.model.ParameterType;
+import org.apache.cxf.jaxrs.model.URITemplate;
 import org.apache.cxf.jaxrs.utils.AnnotationUtils;
 import org.apache.cxf.jaxrs.utils.FormUtils;
 import org.apache.cxf.jaxrs.utils.InjectionUtils;
@@ -920,6 +921,7 @@ public class ClientProxyImpl extends AbstractClient 
implements
                 outMessage.put(PROXY_METHOD_PARAM_BODY_INDEX, bodyIndex);
             }
             outMessage.getInterceptorChain().add(bodyWriter);
+            outMessage.put(URITemplate.URI_TEMPLATE, 
JAXRSUtils.getUriTemplate(outMessage, cri, ori));
 
             Map<String, Object> reqContext = getRequestContext(outMessage);
             reqContext.put(OperationResourceInfo.class.getName(), ori);
diff --git 
a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsApplicationTest.java
 
b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsApplicationTest.java
index b5e2c185373..65630920975 100644
--- 
a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsApplicationTest.java
+++ 
b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsApplicationTest.java
@@ -21,6 +21,7 @@ package org.apache.cxf.systest.jaxrs.spring.boot;
 
 import java.time.Duration;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Map;
 
 import javax.ws.rs.InternalServerErrorException;
@@ -420,7 +421,7 @@ public class SpringJaxrsApplicationTest {
                 entry("exception", "None"),
                 entry("method", "GET"),
                 entry("operation", "getBook"),
-                entry("uri", "http://localhost:"; + port + 
"/api/app/library/100"),
+                entry("uri", "http://localhost:"; + port + 
"/api/app/library/{id}"),
                 entry("outcome", "CLIENT_ERROR"),
                 entry("status", "404"));
     }
@@ -453,10 +454,51 @@ public class SpringJaxrsApplicationTest {
                 entry("status", "UNKNOWN"));
     }
     
+    @Test
+    public void testJaxrsProxySubresourceSuccessMetric() {
+        final LibraryApi api = createApi(port);
+        
+        final Collection<Book> books = api.catalog().getCatalog("cxf");
+        assertThat(books).hasSize(1);
+        
+        await()
+            .atMost(Duration.ofSeconds(1))
+            .ignoreException(MeterNotFoundException.class)
+            .until(() -> registry.get("cxf.server.requests").timers(), 
not(empty()));
+        RequiredSearch serverRequestMetrics = 
registry.get("cxf.server.requests");
+
+        Map<Object, Object> serverTags = 
serverRequestMetrics.timer().getId().getTags().stream()
+                .collect(toMap(Tag::getKey, Tag::getValue));
+
+        assertThat(serverTags)
+            .containsOnly(
+                entry("exception", "None"),
+                entry("method", "GET"),
+                entry("operation", "catalog"),
+                entry("uri", "/api/app/library/catalog/{catalog}"),
+                entry("outcome", "SUCCESS"),
+                entry("status", "200"));
+        
+        RequiredSearch clientRequestMetrics = 
registry.get("cxf.client.requests");
+
+        Map<Object, Object> clientTags = 
clientRequestMetrics.timer().getId().getTags().stream()
+                .collect(toMap(Tag::getKey, Tag::getValue));
+
+        assertThat(clientTags)
+            .containsOnly(
+                entry("exception", "None"),
+                entry("method", "GET"),
+                entry("operation", "getCatalog"),
+                entry("uri", "http://localhost:"; + port + 
"/api/app/library/catalog/{catalog}"),
+                entry("outcome", "SUCCESS"),
+                entry("status", "200"));
+    }
+
     private LibraryApi createApi(int portToUse) {
         final JAXRSClientFactoryBean factory = new JAXRSClientFactoryBean();
         factory.setAddress("http://localhost:"; + portToUse + 
"/api/app/library");
         factory.setFeatures(Arrays.asList(new 
MetricsFeature(metricsProvider)));
+        factory.setProvider(new JacksonJsonProvider());
         factory.setResourceClass(LibraryApi.class);
         return factory.create(LibraryApi.class);
     }
diff --git 
a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsTest.java
 
b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsTest.java
index e32f6bc0f9b..81fc27c14fd 100644
--- 
a/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsTest.java
+++ 
b/systests/spring-boot/src/test/java/org/apache/cxf/systest/jaxrs/spring/boot/SpringJaxrsTest.java
@@ -390,7 +390,7 @@ public class SpringJaxrsTest {
                 entry("exception", "None"),
                 entry("method", "GET"),
                 entry("operation", "getBook"),
-                entry("uri", "http://localhost:"; + port + "/api/library/100"),
+                entry("uri", "http://localhost:"; + port + "/api/library/{id}"),
                 entry("outcome", "CLIENT_ERROR"),
                 entry("status", "404"));
     }

Reply via email to