Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
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.xml.namespace.QName;
Expand Down Expand Up @@ -206,6 +207,7 @@ public final class JAXRSUtils {
"java.util.concurrent.CompletionStage"
));
private static final LazyLoadedClass DATA_SOURCE_CLASS = new LazyLoadedClass("jakarta.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.
Expand Down Expand Up @@ -2114,14 +2116,27 @@ public static String getUriTemplate(Message message, ClassResourceInfo cri, Oper
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
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;
Expand Down Expand Up @@ -921,6 +922,7 @@ protected Object doChainedInvocation(URI uri,
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;

import jakarta.ws.rs.InternalServerErrorException;
Expand Down Expand Up @@ -415,7 +416,7 @@ public void testJaxrsProxyFailedMetric() {
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"));
}
Expand Down Expand Up @@ -448,10 +449,51 @@ public void testJaxrsProxyClientExceptionMetric() {
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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ public void testJaxrsProxyFailedMetric() {
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"));
}
Expand Down