diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java index fd29b345d5..ca0dd64e45 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/routing/UriRoutingContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -34,6 +34,9 @@ import javax.ws.rs.core.UriBuilder; import org.glassfish.jersey.internal.util.collection.ImmutableMultivaluedMap; +import org.glassfish.jersey.internal.util.collection.LazyValue; +import org.glassfish.jersey.internal.util.collection.Value; +import org.glassfish.jersey.internal.util.collection.Values; import org.glassfish.jersey.message.internal.TracingLogger; import org.glassfish.jersey.server.ContainerRequest; import org.glassfish.jersey.server.internal.ServerTraceEvent; @@ -66,7 +69,7 @@ public class UriRoutingContext implements RoutingContext { private final LinkedList matchedLocators = new LinkedList<>(); private final LinkedList locatorSubResources = new LinkedList<>(); - private final TracingLogger tracingLogger; + private final LazyValue tracingLogger; private volatile ResourceMethod matchedResourceMethod = null; private volatile Throwable mappedThrowable = null; @@ -86,7 +89,8 @@ public class UriRoutingContext implements RoutingContext { */ public UriRoutingContext(final ContainerRequest requestContext) { this.requestContext = requestContext; - this.tracingLogger = TracingLogger.getInstance(requestContext); + // Tracing Logger is initialized after UriContext before pushMatchedResource + this.tracingLogger = Values.lazy((Value) () -> TracingLogger.getInstance(requestContext)); } // RoutingContext @@ -97,7 +101,7 @@ public void pushMatchResult(final MatchResult matchResult) { @Override public void pushMatchedResource(final Object resource) { - tracingLogger.log(ServerTraceEvent.MATCH_RESOURCE, resource); + tracingLogger.get().log(ServerTraceEvent.MATCH_RESOURCE, resource); matchedResources.push(resource); } @@ -108,7 +112,7 @@ public Object peekMatchedResource() { @Override public void pushMatchedLocator(final ResourceMethod resourceLocator) { - tracingLogger.log(ServerTraceEvent.MATCH_LOCATOR, resourceLocator.getInvocable().getHandlingMethod()); + tracingLogger.get().log(ServerTraceEvent.MATCH_LOCATOR, resourceLocator.getInvocable().getHandlingMethod()); matchedLocators.push(resourceLocator); } @@ -189,14 +193,14 @@ public Endpoint getEndpoint() { @Override public void setMatchedResourceMethod(final ResourceMethod resourceMethod) { - tracingLogger.log(ServerTraceEvent.MATCH_RESOURCE_METHOD, resourceMethod.getInvocable().getHandlingMethod()); + tracingLogger.get().log(ServerTraceEvent.MATCH_RESOURCE_METHOD, resourceMethod.getInvocable().getHandlingMethod()); this.matchedResourceMethod = resourceMethod; } @Override public void pushMatchedRuntimeResource(final RuntimeResource runtimeResource) { - if (tracingLogger.isLogEnabled(ServerTraceEvent.MATCH_RUNTIME_RESOURCE)) { - tracingLogger.log(ServerTraceEvent.MATCH_RUNTIME_RESOURCE, + if (tracingLogger.get().isLogEnabled(ServerTraceEvent.MATCH_RUNTIME_RESOURCE)) { + tracingLogger.get().log(ServerTraceEvent.MATCH_RUNTIME_RESOURCE, runtimeResource.getResources().get(0).getPath(), runtimeResource.getResources().get(0).getPathPattern().getRegex(), matchResults.peek().group() diff --git a/tests/integration/tracing-support/pom.xml b/tests/integration/tracing-support/pom.xml index a7a35f0cba..62268abbe8 100644 --- a/tests/integration/tracing-support/pom.xml +++ b/tests/integration/tracing-support/pom.xml @@ -43,10 +43,25 @@ jersey-test-framework-provider-external test + + + org.glassfish.jersey.test-framework.providers + jersey-test-framework-provider-grizzly2 + test + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${project.build.testOutputDirectory}/logging.properties + + + org.apache.maven.plugins maven-compiler-plugin diff --git a/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/TracingMatchResourceMethodTest.java b/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/TracingMatchResourceMethodTest.java new file mode 100644 index 0000000000..3629513452 --- /dev/null +++ b/tests/integration/tracing-support/src/test/java/org/glassfish/jersey/tests/integration/tracing/TracingMatchResourceMethodTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.tests.integration.tracing; + +import org.glassfish.jersey.message.internal.TracingLogger; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.server.ServerProperties; +import org.glassfish.jersey.server.TracingConfig; +import org.glassfish.jersey.server.internal.ServerTraceEvent; +import org.glassfish.jersey.test.JerseyTest; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class TracingMatchResourceMethodTest extends JerseyTest { + GatheringHandler handler = new GatheringHandler(); + Logger logger; + + @Path("/echo") + public static class TracingMatchResourceMethodResource { + @Path("echo") + @POST + public String echo(String entity) { + return entity; + } + } + + @Override + protected Application configure() { + return new ResourceConfig(TracingMatchResourceMethodResource.class) + .property(ServerProperties.TRACING, TracingConfig.ALL.name()) + .property(ServerProperties.TRACING_THRESHOLD, TracingLogger.Level.VERBOSE.name()); + } + + @Test + public void testEcho() { + logger = Logger.getLogger("org.glassfish.jersey.tracing.general"); + logger.addHandler(handler); + + try (Response r = target("echo").path("echo").request().post(Entity.entity("ECHO", MediaType.TEXT_PLAIN_TYPE))) { + MatcherAssert.assertThat(r.getStatus(), Matchers.equalTo(200)); + MatcherAssert.assertThat(r.readEntity(String.class), Matchers.equalTo("ECHO")); + } + + List matched = handler.logRecords.stream() + .filter(logRecord -> logRecord.getMessage().startsWith(ServerTraceEvent.MATCH_RESOURCE_METHOD.name())) + .collect(Collectors.toList()); + MatcherAssert.assertThat(matched.size(), Matchers.equalTo(1)); + } + + private static class GatheringHandler extends Handler { + + List logRecords = new ArrayList<>(); + + @Override + public void publish(LogRecord record) { + logRecords.add(record); + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + } +}