diff --git a/changelog/@unreleased/pr-959.v2.yml b/changelog/@unreleased/pr-959.v2.yml new file mode 100644 index 000000000..593c3a4ac --- /dev/null +++ b/changelog/@unreleased/pr-959.v2.yml @@ -0,0 +1,12 @@ +type: improvement +improvement: + description: |- + Introduced jakarta equivalents of all modules which had a javax dependency + + Additionally had to do a few things: + + 1. Migrated from spotify's ADT to derive4j which generates types without a legacy javax.annotation.Generated type + 2. Fixed a few tests + 3. Upgraded newer libraries to Junit5 + links: + - https://github.com/palantir/tracing-java/pull/959 diff --git a/settings.gradle b/settings.gradle index 8640fb1b2..d6d22b2ff 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,9 +4,13 @@ include 'tracing' include 'tracing-api' include 'tracing-benchmarks' include 'tracing-demos' -include 'tracing-jaxrs' -include 'tracing-jersey' include 'tracing-okhttp3' -include 'tracing-servlet' include 'tracing-test-utils' include 'tracing-undertow' + +include 'tracing-servlet' +include 'tracing-jaxrs' +include 'tracing-jersey' +include 'tracing-servlet-jakarta' +include 'tracing-jaxrs-jakarta' +include 'tracing-jersey-jakarta' diff --git a/tracing-jaxrs-jakarta/build.gradle b/tracing-jaxrs-jakarta/build.gradle new file mode 100644 index 000000000..cfed5dc6d --- /dev/null +++ b/tracing-jaxrs-jakarta/build.gradle @@ -0,0 +1,31 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: 'org.inferred.processors' + +apply plugin: 'com.palantir.external-publish-jar' +apply plugin: 'com.palantir.revapi' + +dependencies { + api project(":tracing") + api "jakarta.ws.rs:jakarta.ws.rs-api" + + testImplementation "ch.qos.logback:logback-classic" + testImplementation "junit:junit" + testImplementation "org.assertj:assertj-core" + testImplementation "org.jmock:jmock" + testImplementation "org.mockito:mockito-core" +} diff --git a/tracing-jaxrs-jakarta/src/main/java/com/palantir/tracing/jaxrs/JaxRsTracers.java b/tracing-jaxrs-jakarta/src/main/java/com/palantir/tracing/jaxrs/JaxRsTracers.java new file mode 100644 index 000000000..88e0ca9fd --- /dev/null +++ b/tracing-jaxrs-jakarta/src/main/java/com/palantir/tracing/jaxrs/JaxRsTracers.java @@ -0,0 +1,55 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.tracing.jaxrs; + +import com.palantir.tracing.CloseableSpan; +import com.palantir.tracing.Detached; +import com.palantir.tracing.DetachedSpan; +import com.palantir.tracing.Tracers; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.core.StreamingOutput; +import java.io.IOException; +import java.io.OutputStream; +import java.util.concurrent.Callable; + +public final class JaxRsTracers { + + private JaxRsTracers() {} + + /** Like {@link Tracers#wrap(Callable)}, but for StreamingOutputs. */ + public static StreamingOutput wrap(StreamingOutput delegate) { + return new TracingAwareStreamingOutput(delegate); + } + + private static class TracingAwareStreamingOutput implements StreamingOutput { + + private final StreamingOutput delegate; + private final Detached detached; + + TracingAwareStreamingOutput(StreamingOutput delegate) { + this.delegate = delegate; + this.detached = DetachedSpan.detach(); + } + + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + try (CloseableSpan ignored = detached.childSpan("streaming-output")) { + delegate.write(output); + } + } + } +} diff --git a/tracing-jaxrs-jakarta/src/test/java/com/palantir/tracing/jaxrs/JaxRsTracersTest.java b/tracing-jaxrs-jakarta/src/test/java/com/palantir/tracing/jaxrs/JaxRsTracersTest.java new file mode 100644 index 000000000..90634f831 --- /dev/null +++ b/tracing-jaxrs-jakarta/src/test/java/com/palantir/tracing/jaxrs/JaxRsTracersTest.java @@ -0,0 +1,84 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.tracing.jaxrs; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.palantir.tracing.AlwaysSampler; +import com.palantir.tracing.Tracer; +import jakarta.ws.rs.core.StreamingOutput; +import java.io.ByteArrayOutputStream; +import org.junit.Test; + +public final class JaxRsTracersTest { + + @Test + public void testWrappingStreamingOutput_streamingOutputTraceIsIsolated_sampled() throws Exception { + Tracer.setSampler(AlwaysSampler.INSTANCE); + Tracer.getAndClearTrace(); + + Tracer.fastStartSpan("outside"); + StreamingOutput streamingOutput = JaxRsTracers.wrap(_os -> { + Tracer.fastStartSpan("inside"); // never completed + }); + streamingOutput.write(new ByteArrayOutputStream()); + assertThat(Tracer.completeSpan().get().getOperation()).isEqualTo("outside"); + } + + @Test + public void testWrappingStreamingOutput_streamingOutputTraceIsIsolated_unsampled() throws Exception { + Tracer.setSampler(() -> false); + Tracer.getAndClearTrace(); + + Tracer.fastStartSpan("outside"); + StreamingOutput streamingOutput = JaxRsTracers.wrap(_os -> { + Tracer.fastStartSpan("inside"); // never completed + }); + streamingOutput.write(new ByteArrayOutputStream()); + assertThat(Tracer.hasTraceId()).isTrue(); + Tracer.fastCompleteSpan(); + assertThat(Tracer.hasTraceId()).isFalse(); + } + + @Test + public void testWrappingStreamingOutput_traceStateIsCapturedAtConstructionTime_sampled() throws Exception { + Tracer.setSampler(AlwaysSampler.INSTANCE); + Tracer.getAndClearTrace(); + + Tracer.fastStartSpan("before-construction"); + StreamingOutput streamingOutput = JaxRsTracers.wrap(_os -> { + assertThat(Tracer.completeSpan().get().getOperation()).isEqualTo("streaming-output"); + }); + Tracer.fastStartSpan("after-construction"); + streamingOutput.write(new ByteArrayOutputStream()); + } + + @Test + public void testWrappingStreamingOutput_traceStateIsCapturedAtConstructionTime_unsampled() throws Exception { + Tracer.setSampler(() -> false); + Tracer.getAndClearTrace(); + + Tracer.fastStartSpan("before-construction"); + StreamingOutput streamingOutput = JaxRsTracers.wrap(_os -> { + assertThat(Tracer.hasTraceId()).isTrue(); + Tracer.fastCompleteSpan(); + assertThat(Tracer.hasTraceId()).isFalse(); + }); + Tracer.fastStartSpan("after-construction"); + streamingOutput.write(new ByteArrayOutputStream()); + } +} diff --git a/tracing-jaxrs/build.gradle b/tracing-jaxrs/build.gradle index cfed5dc6d..eb8bbdc98 100644 --- a/tracing-jaxrs/build.gradle +++ b/tracing-jaxrs/build.gradle @@ -19,9 +19,13 @@ apply plugin: 'org.inferred.processors' apply plugin: 'com.palantir.external-publish-jar' apply plugin: 'com.palantir.revapi' +versionsLock { + disableJavaPluginDefaults() +} + dependencies { api project(":tracing") - api "jakarta.ws.rs:jakarta.ws.rs-api" + api "javax.ws.rs:javax.ws.rs-api" testImplementation "ch.qos.logback:logback-classic" testImplementation "junit:junit" diff --git a/tracing-jersey-jakarta/build.gradle b/tracing-jersey-jakarta/build.gradle new file mode 100644 index 000000000..7dc127f14 --- /dev/null +++ b/tracing-jersey-jakarta/build.gradle @@ -0,0 +1,34 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: 'com.palantir.external-publish-jar' +apply plugin: 'com.palantir.revapi' + +dependencies { + api project(":tracing") + + implementation "org.glassfish.jersey.core:jersey-server" + implementation 'com.google.guava:guava' + implementation 'jakarta.ws.rs:jakarta.ws.rs-api' + implementation project(':tracing-api') + + testImplementation "io.dropwizard:dropwizard-testing" + testImplementation "org.junit.jupiter:junit-jupiter" + testImplementation "org.assertj:assertj-core" + testImplementation "org.hamcrest:hamcrest-all" + testImplementation "org.mockito:mockito-core" + testImplementation "org.mockito:mockito-junit-jupiter" +} diff --git a/tracing-jersey-jakarta/src/main/java/com/palantir/tracing/jersey/TraceEnrichingFilter.java b/tracing-jersey-jakarta/src/main/java/com/palantir/tracing/jersey/TraceEnrichingFilter.java new file mode 100644 index 000000000..3e7c14912 --- /dev/null +++ b/tracing-jersey-jakarta/src/main/java/com/palantir/tracing/jersey/TraceEnrichingFilter.java @@ -0,0 +1,177 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.tracing.jersey; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Strings; +import com.palantir.tracing.Observability; +import com.palantir.tracing.TagTranslator; +import com.palantir.tracing.TraceMetadata; +import com.palantir.tracing.Tracer; +import com.palantir.tracing.Tracers; +import com.palantir.tracing.api.SpanType; +import com.palantir.tracing.api.TraceHttpHeaders; +import com.palantir.tracing.api.TraceTags; +import jakarta.annotation.Priority; +import jakarta.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.container.ContainerRequestFilter; +import jakarta.ws.rs.container.ContainerResponseContext; +import jakarta.ws.rs.container.ContainerResponseFilter; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.ext.Provider; +import java.io.IOException; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import org.glassfish.jersey.server.ExtendedUriInfo; +import org.glassfish.jersey.server.model.Resource; + +// Default is `Priorities.USER` == 5000. This filter needs to execute earlier to ensure traces are ready to use. +@Priority(500) +@Provider +public final class TraceEnrichingFilter implements ContainerRequestFilter, ContainerResponseFilter { + public static final TraceEnrichingFilter INSTANCE = new TraceEnrichingFilter(); + + /** + * This is the name of the trace id property we set on {@link ContainerRequestContext}. + */ + public static final String TRACE_ID_PROPERTY_NAME = "com.palantir.tracing.traceId"; + + public static final String REQUEST_ID_PROPERTY_NAME = "com.palantir.tracing.requestId"; + + public static final String SAMPLED_PROPERTY_NAME = "com.palantir.tracing.sampled"; + + @VisibleForTesting + static final String FETCH_USER_AGENT_HEADER = "Fetch-User-Agent"; + + @Context + @SuppressWarnings("NullAway") // instantiated using by Jersey using reflection + private ExtendedUriInfo uriInfo; + + // Handles incoming request + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + String path = getPathTemplate(); + + String operation = "Jersey: " + requestContext.getMethod() + " " + path; + // The following strings are all nullable + String traceId = requestContext.getHeaderString(TraceHttpHeaders.TRACE_ID); + String spanId = requestContext.getHeaderString(TraceHttpHeaders.SPAN_ID); + Optional forUserAgent = getForUserAgent(requestContext); + + // Set up thread-local span that inherits state from HTTP headers + if (Strings.isNullOrEmpty(traceId)) { + // HTTP request did not indicate a trace; initialize trace state and create a span. + Tracer.initTraceWithSpan( + getObservabilityFromHeader(requestContext), + Tracers.randomId(), + forUserAgent, + operation, + SpanType.SERVER_INCOMING); + } else if (spanId == null) { + Tracer.initTraceWithSpan( + getObservabilityFromHeader(requestContext), + traceId, + forUserAgent, + operation, + SpanType.SERVER_INCOMING); + } else { + // caller's span is this span's parent. + Tracer.initTraceWithSpan( + getObservabilityFromHeader(requestContext), + traceId, + forUserAgent, + operation, + spanId, + SpanType.SERVER_INCOMING); + } + + // Give asynchronous downstream handlers access to the trace id + requestContext.setProperty(TRACE_ID_PROPERTY_NAME, Tracer.getTraceId()); + requestContext.setProperty(SAMPLED_PROPERTY_NAME, Tracer.isTraceObservable()); + Tracer.maybeGetTraceMetadata() + .flatMap(TraceMetadata::getRequestId) + .ifPresent(requestId -> requestContext.setProperty(REQUEST_ID_PROPERTY_NAME, requestId)); + } + + // Handles outgoing response + @Override + public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + MultivaluedMap headers = responseContext.getHeaders(); + if (Tracer.hasTraceId()) { + String traceId = Tracer.getTraceId(); + Tracer.fastCompleteSpan(FunctionalTagTranslator.INSTANCE, sink -> { + sink.accept(TraceTags.HTTP_STATUS_CODE, Integer.toString(responseContext.getStatus())); + sink.accept(TraceTags.HTTP_URL_PATH_TEMPLATE, getPathTemplate()); + sink.accept(TraceTags.HTTP_METHOD, requestContext.getMethod()); + Object requestId = requestContext.getProperty(REQUEST_ID_PROPERTY_NAME); + if (requestId instanceof String) { + sink.accept(TraceTags.HTTP_REQUEST_ID, (String) requestId); + } + }); + headers.putSingle(TraceHttpHeaders.TRACE_ID, traceId); + } else { + // When the filter is called twice (e.g. an exception is thrown in a streaming call), + // the current trace will be empty. To allow clients to still get the trace ID corresponding to + // the failure, we retrieve it from the requestContext. + Optional.ofNullable(requestContext.getProperty(TRACE_ID_PROPERTY_NAME)) + .ifPresent(s -> headers.putSingle(TraceHttpHeaders.TRACE_ID, s)); + } + } + + // Force sample iff the context contains a "1" X-B3-Sampled header, force not sample if the header contains another + // non-empty value, or undecided if there is no such header or the header is empty. + private static Observability getObservabilityFromHeader(ContainerRequestContext context) { + String header = context.getHeaderString(TraceHttpHeaders.IS_SAMPLED); + if (Strings.isNullOrEmpty(header)) { + return Observability.UNDECIDED; + } else { + return "1".equals(header) ? Observability.SAMPLE : Observability.DO_NOT_SAMPLE; + } + } + + private static Optional getForUserAgent(ContainerRequestContext context) { + String forUserAgent = context.getHeaderString(TraceHttpHeaders.FOR_USER_AGENT); + if (forUserAgent != null) { + return Optional.of(forUserAgent); + } + String fetchUserAgent = context.getHeaderString(FETCH_USER_AGENT_HEADER); + if (fetchUserAgent != null) { + return Optional.of(fetchUserAgent); + } + return Optional.ofNullable(context.getHeaderString(HttpHeaders.USER_AGENT)); + } + + private String getPathTemplate() { + return Optional.ofNullable(uriInfo) + .map(ExtendedUriInfo::getMatchedModelResource) + .map(Resource::getPath) + .orElse("(unknown)"); + } + + private enum FunctionalTagTranslator implements TagTranslator>> { + INSTANCE; + + @Override + public void translate(TagAdapter adapter, T target, Consumer> data) { + data.accept((key, value) -> adapter.tag(target, key, value)); + } + } +} diff --git a/tracing-jersey/src/test/java/com/palantir/tracing/jersey/TraceEnrichingFilterTest.java b/tracing-jersey-jakarta/src/test/java/com/palantir/tracing/jersey/TraceEnrichingFilterTest.java similarity index 90% rename from tracing-jersey/src/test/java/com/palantir/tracing/jersey/TraceEnrichingFilterTest.java rename to tracing-jersey-jakarta/src/test/java/com/palantir/tracing/jersey/TraceEnrichingFilterTest.java index 33fde0729..04c34da5b 100644 --- a/tracing-jersey/src/test/java/com/palantir/tracing/jersey/TraceEnrichingFilterTest.java +++ b/tracing-jersey-jakarta/src/test/java/com/palantir/tracing/jersey/TraceEnrichingFilterTest.java @@ -34,42 +34,44 @@ import com.palantir.tracing.api.SpanType; import com.palantir.tracing.api.TraceHttpHeaders; import com.palantir.tracing.api.TraceTags; -import io.dropwizard.Application; -import io.dropwizard.Configuration; -import io.dropwizard.setup.Environment; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.Entity; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; -import javax.ws.rs.core.UriInfo; +import io.dropwizard.core.Application; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.container.ContainerRequestContext; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.StreamingOutput; +import jakarta.ws.rs.core.UriInfo; import org.glassfish.jersey.client.JerseyClientBuilder; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; import org.slf4j.MDC; -@RunWith(MockitoJUnitRunner.class) +@ExtendWith(DropwizardExtensionsSupport.class) +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) public final class TraceEnrichingFilterTest { - @ClassRule - @SuppressWarnings("deprecation") - public static final io.dropwizard.testing.junit.DropwizardAppRule APP = - new io.dropwizard.testing.junit.DropwizardAppRule<>( + public static final io.dropwizard.testing.junit5.DropwizardAppExtension APP = + new io.dropwizard.testing.junit5.DropwizardAppExtension<>( TracingTestServer.class, "src/test/resources/test-server.yml"); @Captor @@ -89,7 +91,7 @@ public final class TraceEnrichingFilterTest { private WebTarget target; - @Before + @BeforeEach public void before() { String endpointUri = "http://localhost:" + APP.getLocalPort(); JerseyClientBuilder builder = new JerseyClientBuilder(); @@ -104,7 +106,7 @@ public void before() { when(traceSampler.sample()).thenReturn(true); } - @After + @AfterEach public void after() { Tracer.unsubscribe(""); } diff --git a/tracing-jersey/src/test/resources/test-server.yml b/tracing-jersey-jakarta/src/test/resources/test-server.yml similarity index 100% rename from tracing-jersey/src/test/resources/test-server.yml rename to tracing-jersey-jakarta/src/test/resources/test-server.yml diff --git a/tracing-jersey/build.gradle b/tracing-jersey/build.gradle index f30c08f89..e5ceb1c7e 100644 --- a/tracing-jersey/build.gradle +++ b/tracing-jersey/build.gradle @@ -17,17 +17,27 @@ apply plugin: 'com.palantir.external-publish-jar' apply plugin: 'com.palantir.revapi' +versionsLock { + disableJavaPluginDefaults() +} + dependencies { - api "org.glassfish.jersey.core:jersey-server" + implementation "org.glassfish.jersey.core:jersey-server", { + version { + strictly "2.22.2" + because "need to pin to the javax version of Jersey" + } + } api project(":tracing") implementation 'com.google.guava:guava' - implementation 'jakarta.ws.rs:jakarta.ws.rs-api' + implementation 'javax.ws.rs:javax.ws.rs-api' implementation project(':tracing-api') - testImplementation "io.dropwizard:dropwizard-testing" - testImplementation "junit:junit" - testImplementation "org.assertj:assertj-core" - testImplementation "org.hamcrest:hamcrest-all" - testImplementation "org.mockito:mockito-core" + modules { + module("org.glassfish.hk2.external:javax.inject") { + replacedBy('javax.inject:javax.inject', 'javax version is preferred') + } + } + } diff --git a/tracing-servlet-jakarta/build.gradle b/tracing-servlet-jakarta/build.gradle new file mode 100644 index 000000000..7dce47979 --- /dev/null +++ b/tracing-servlet-jakarta/build.gradle @@ -0,0 +1,32 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: 'com.palantir.external-publish-jar' +apply plugin: 'com.palantir.revapi' + +dependencies { + // tracing is used to clear tracing state, but not exposed to other consumers + implementation project(":tracing") + + // servlet-api should be the only exposed dependency + api "jakarta.servlet:jakarta.servlet-api" + + implementation 'com.palantir.safe-logging:logger' + + testImplementation "io.dropwizard:dropwizard-testing" + testImplementation "org.junit.jupiter:junit-jupiter" + testImplementation 'org.assertj:assertj-core' +} diff --git a/tracing-servlet-jakarta/src/main/java/com/palantir/tracing/servlet/LeakedTraceFilter.java b/tracing-servlet-jakarta/src/main/java/com/palantir/tracing/servlet/LeakedTraceFilter.java new file mode 100644 index 000000000..57ef9fb7b --- /dev/null +++ b/tracing-servlet-jakarta/src/main/java/com/palantir/tracing/servlet/LeakedTraceFilter.java @@ -0,0 +1,93 @@ +/* + * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.tracing.servlet; + +import com.palantir.logsafe.SafeArg; +import com.palantir.logsafe.UnsafeArg; +import com.palantir.logsafe.logger.SafeLogger; +import com.palantir.logsafe.logger.SafeLoggerFactory; +import com.palantir.tracing.Trace; +import com.palantir.tracing.Tracer; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Objects; + +/** + * Guarantees clean {@link Tracer} thread state for incoming requests. This {@link Filter} logs at + * + *
DEBUG
+ * + * level when another a leaked trace is encountered on the pooled server thread, as well as when the operation wrapped + * by this filter has leaked state. + */ +public final class LeakedTraceFilter implements Filter { + private static final SafeLogger log = SafeLoggerFactory.get(LeakedTraceFilter.class); + + @Override + public void init(FilterConfig _value) { + // nop + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + if (Tracer.hasTraceId()) { + Trace leakedTrace = Tracer.getAndClearTrace(); + if (log.isDebugEnabled()) { + log.debug("Clearing leaked trace trace {}", SafeArg.of("trace", toLoggableValue(leakedTrace))); + } + } + try { + chain.doFilter(request, response); + } finally { + if (Tracer.hasTraceId()) { + Trace leakedTrace = Tracer.getAndClearTrace(); + if (log.isDebugEnabled()) { + log.debug( + "This operation has leaked Tracer state. Tracer.startSpan was executed without " + + "Tracer.completeSpan, resulting in both loss of span data and spans using " + + "completion information from incorrect operations. Trace: {}, Path: {}", + SafeArg.of("trace", toLoggableValue(leakedTrace)), + UnsafeArg.of("path", getPath(request))); + } + } + } + } + + private static String toLoggableValue(Trace trace) { + // Use the trace toString value, the Trace object is not meant to be JSON serializable + return Objects.toString(trace); + } + + private static String getPath(ServletRequest request) { + if (request instanceof HttpServletRequest) { + return ((HttpServletRequest) request).getRequestURI(); + } + return "Unknown"; + } + + @Override + public void destroy() { + // nop + } +} diff --git a/tracing-servlet/src/test/java/com/palantir/tracing/servlet/LeakedTraceFilterTest.java b/tracing-servlet-jakarta/src/test/java/com/palantir/tracing/servlet/LeakedTraceFilterTest.java similarity index 85% rename from tracing-servlet/src/test/java/com/palantir/tracing/servlet/LeakedTraceFilterTest.java rename to tracing-servlet-jakarta/src/test/java/com/palantir/tracing/servlet/LeakedTraceFilterTest.java index f3eac12dd..626332fed 100644 --- a/tracing-servlet/src/test/java/com/palantir/tracing/servlet/LeakedTraceFilterTest.java +++ b/tracing-servlet-jakarta/src/test/java/com/palantir/tracing/servlet/LeakedTraceFilterTest.java @@ -20,39 +20,39 @@ import com.palantir.tracing.AlwaysSampler; import com.palantir.tracing.Tracer; -import io.dropwizard.Application; -import io.dropwizard.Configuration; -import io.dropwizard.setup.Environment; +import io.dropwizard.core.Application; +import io.dropwizard.core.Configuration; +import io.dropwizard.core.setup.Environment; +import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.Response; import java.io.IOException; import java.util.EnumSet; -import javax.servlet.DispatcherType; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Response; import org.glassfish.jersey.client.JerseyClientBuilder; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +@ExtendWith(DropwizardExtensionsSupport.class) public class LeakedTraceFilterTest { - @ClassRule - @SuppressWarnings("deprecation") - public static final io.dropwizard.testing.junit.DropwizardAppRule APP = - new io.dropwizard.testing.junit.DropwizardAppRule<>( + public static final io.dropwizard.testing.junit5.DropwizardAppExtension APP = + new io.dropwizard.testing.junit5.DropwizardAppExtension<>( TracingTestServer.class, "src/test/resources/test-server.yml"); private WebTarget target; - @Before + @BeforeEach public void before() { String endpointUri = "http://localhost:" + APP.getLocalPort(); JerseyClientBuilder builder = new JerseyClientBuilder(); diff --git a/tracing-servlet/src/test/resources/test-server.yml b/tracing-servlet-jakarta/src/test/resources/test-server.yml similarity index 100% rename from tracing-servlet/src/test/resources/test-server.yml rename to tracing-servlet-jakarta/src/test/resources/test-server.yml diff --git a/tracing-servlet/build.gradle b/tracing-servlet/build.gradle index 5621f7380..5ff330c3a 100644 --- a/tracing-servlet/build.gradle +++ b/tracing-servlet/build.gradle @@ -17,16 +17,16 @@ apply plugin: 'com.palantir.external-publish-jar' apply plugin: 'com.palantir.revapi' +versionsLock { + disableJavaPluginDefaults() +} + dependencies { // tracing is used to clear tracing state, but not exposed to other consumers implementation project(":tracing") // servlet-api should be the only exposed dependency - api "jakarta.servlet:jakarta.servlet-api" + api "javax.servlet:javax.servlet-api" implementation 'com.palantir.safe-logging:logger' - - testImplementation "io.dropwizard:dropwizard-testing" - testImplementation "junit:junit" - testImplementation 'org.assertj:assertj-core' -} +} \ No newline at end of file diff --git a/tracing-test-utils/build.gradle b/tracing-test-utils/build.gradle index 1a434bc6c..12c25b484 100644 --- a/tracing-test-utils/build.gradle +++ b/tracing-test-utils/build.gradle @@ -9,10 +9,10 @@ dependencies { compileOnly 'junit:junit' compileOnly 'org.junit.jupiter:junit-jupiter-api' implementation 'com.palantir.conjure.java.runtime:conjure-java-jackson-serialization' - implementation 'com.spotify.dataenum:dataenum' + compileOnly "org.derive4j:derive4j-annotation" implementation "org.slf4j:slf4j-api" - annotationProcessor 'com.spotify.dataenum:dataenum-processor' + annotationProcessor "org.derive4j:derive4j" annotationProcessor "org.immutables:value" compileOnly "org.immutables:value::annotations" compileOnly "jakarta.annotation:jakarta.annotation-api" diff --git a/tracing-test-utils/src/main/java/com/palantir/tracing/ComparisonFailure_dataenum.java b/tracing-test-utils/src/main/java/com/palantir/tracing/ComparisonFailure.java similarity index 66% rename from tracing-test-utils/src/main/java/com/palantir/tracing/ComparisonFailure_dataenum.java rename to tracing-test-utils/src/main/java/com/palantir/tracing/ComparisonFailure.java index d0b187785..31227bd3b 100644 --- a/tracing-test-utils/src/main/java/com/palantir/tracing/ComparisonFailure_dataenum.java +++ b/tracing-test-utils/src/main/java/com/palantir/tracing/ComparisonFailure.java @@ -17,16 +17,20 @@ package com.palantir.tracing; import com.palantir.tracing.api.Span; -import com.spotify.dataenum.DataEnum; -import com.spotify.dataenum.dataenum_case; import java.util.List; +import org.derive4j.Data; @SuppressWarnings("checkstyle:TypeName") -@DataEnum -interface ComparisonFailure_dataenum { - dataenum_case unequalOperation(Span expected, Span actual); +@Data +public abstract class ComparisonFailure { - dataenum_case unequalChildren(Span expected, Span actual, List expectedChildren, List actualChildren); + interface Cases { + R unequalOperation(Span expected, Span actual); - dataenum_case incompatibleStructure(Span expected, Span actual); + R unequalChildren(Span expected, Span actual, List expectedChildren, List actualChildren); + + R incompatibleStructure(Span expected, Span actual); + } + + public abstract R match(Cases cases); } diff --git a/tracing-test-utils/src/main/java/com/palantir/tracing/SpanAnalyzer.java b/tracing-test-utils/src/main/java/com/palantir/tracing/SpanAnalyzer.java index 5452ecce6..01382d987 100644 --- a/tracing-test-utils/src/main/java/com/palantir/tracing/SpanAnalyzer.java +++ b/tracing-test-utils/src/main/java/com/palantir/tracing/SpanAnalyzer.java @@ -113,7 +113,7 @@ public static Map analyzeByTraceId(Collection spans) { static Stream compareSpansRecursively(Result expected, Result actual, Span ex, Span ac) { if (!ex.getOperation().equals(ac.getOperation())) { - return Stream.of(ComparisonFailure.unequalOperation(ex, ac)); + return Stream.of(ComparisonFailures.unequalOperation(ex, ac)); } // other fields, type, params, metadata(???) @@ -122,14 +122,14 @@ static Stream compareSpansRecursively(Result expected, Result List sortedActualChildren = sortedChildren(actual.graph(), ac); if (sortedExpectedChildren.size() != sortedActualChildren.size()) { // just highlighting the parents for now. - return Stream.of(ComparisonFailure.unequalChildren(ex, ac, sortedExpectedChildren, sortedActualChildren)); + return Stream.of(ComparisonFailures.unequalChildren(ex, ac, sortedExpectedChildren, sortedActualChildren)); } boolean expectedContainsOverlappingSpans = containsOverlappingSpans(sortedExpectedChildren); boolean actualContainsOverlappingSpans = containsOverlappingSpans(sortedActualChildren); if (expectedContainsOverlappingSpans ^ actualContainsOverlappingSpans) { // Either Both or neither tree should have concurrent spans - return Stream.of(ComparisonFailure.incompatibleStructure(ex, ac)); + return Stream.of(ComparisonFailures.incompatibleStructure(ex, ac)); } if (!actualContainsOverlappingSpans) { @@ -140,7 +140,7 @@ static Stream compareSpansRecursively(Result expected, Result } if (!compatibleOverlappingSpans(expected, actual, sortedExpectedChildren, sortedActualChildren)) { - return Stream.of(ComparisonFailure.unequalChildren(ex, ac, sortedExpectedChildren, sortedActualChildren)); + return Stream.of(ComparisonFailures.unequalChildren(ex, ac, sortedExpectedChildren, sortedActualChildren)); } return Stream.empty(); } diff --git a/tracing-test-utils/src/main/java/com/palantir/tracing/TestTracingExtension.java b/tracing-test-utils/src/main/java/com/palantir/tracing/TestTracingExtension.java index cc51141b8..4a0f86357 100644 --- a/tracing-test-utils/src/main/java/com/palantir/tracing/TestTracingExtension.java +++ b/tracing-test-utils/src/main/java/com/palantir/tracing/TestTracingExtension.java @@ -106,10 +106,11 @@ public void afterTestExecution(ExtensionContext context) throws Exception { .path(actualPath) .displayName("actual") .problemSpanIds(failures.stream() - .map(res -> res.map( - ComparisonFailure.unequalOperation::expected, - ComparisonFailure.unequalChildren::expected, - ComparisonFailure.incompatibleStructure::expected)) + .map(res -> ComparisonFailures.cases() + .unequalOperation((e, _a) -> e) + .unequalChildren((e, _a, _ec, _ac) -> e) + .incompatibleStructure((e, _a) -> e) + .apply(res)) .map(Span::getSpanId) .collect(ImmutableSet.toImmutableSet())) .layoutStrategy(annotation.layout()) @@ -120,10 +121,11 @@ public void afterTestExecution(ExtensionContext context) throws Exception { .path(expectedPath) .displayName("expected") .problemSpanIds(failures.stream() - .map(res -> res.map( - ComparisonFailure.unequalOperation::actual, - ComparisonFailure.unequalChildren::actual, - ComparisonFailure.incompatibleStructure::actual)) + .map(res -> ComparisonFailures.cases() + .unequalOperation((_e, a) -> a) + .unequalChildren((_e, a, _ec, _ac) -> a) + .incompatibleStructure((_e, a) -> a) + .apply(res)) .map(Span::getSpanId) .collect(ImmutableSet.toImmutableSet())) .layoutStrategy(annotation.layout()) @@ -145,16 +147,15 @@ public void afterTestExecution(ExtensionContext context) throws Exception { } private static String renderFailure(ComparisonFailure failure) { - return failure.map( - (ComparisonFailure.unequalOperation t) -> String.format( - "Expected operation %s but received %s", - t.expected().getOperation(), t.actual().getOperation()), - (ComparisonFailure.unequalChildren t) -> String.format( + return ComparisonFailures.cases() + .unequalOperation((expected, actual) -> String.format( + "Expected operation %s but received %s", expected.getOperation(), actual.getOperation())) + .unequalChildren((_e, _a, expectedChildren, actualChildren) -> String.format( "Expected children with operations %s but received %s", - t.expectedChildren().stream().map(Span::getOperation).collect(ImmutableList.toImmutableList()), - t.actualChildren().stream().map(Span::getOperation).collect(ImmutableList.toImmutableList())), - (ComparisonFailure.incompatibleStructure _t) -> - String.format("Expected children to structured similarly")); + expectedChildren.stream().map(Span::getOperation).collect(ImmutableList.toImmutableList()), + actualChildren.stream().map(Span::getOperation).collect(ImmutableList.toImmutableList()))) + .incompatibleStructure((_e, _a) -> "Expected children to be structured similarly") + .apply(failure); } private static String testName(ExtensionContext context) { diff --git a/versions.lock b/versions.lock index 08cb92f59..5da4ea8b0 100644 --- a/versions.lock +++ b/versions.lock @@ -1,8 +1,8 @@ # Run ./gradlew --write-locks to regenerate this file -com.google.code.findbugs:jsr305:3.0.2 (16 constraints: 50e8dc30) -com.google.errorprone:error_prone_annotations:2.11.0 (6 constraints: 5b59fd7f) +com.google.code.findbugs:jsr305:3.0.2 (2 constraints: cd195721) +com.google.errorprone:error_prone_annotations:2.14.0 (8 constraints: a177c002) com.google.guava:failureaccess:1.0.1 (1 constraints: 140ae1b4) -com.google.guava:guava:28.2-jre (6 constraints: 5d5b5723) +com.google.guava:guava:31.1-jre (5 constraints: ae4c2294) com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava (1 constraints: bd17c918) com.google.j2objc:j2objc-annotations:1.3 (1 constraints: b809eda0) com.palantir.safe-logging:logger:1.25.0 (1 constraints: 3c05413b) @@ -13,134 +13,144 @@ com.palantir.safe-logging:safe-logging:1.25.0 (5 constraints: a848cc21) com.squareup.okhttp3:okhttp:3.9.0 (1 constraints: 0e051536) com.squareup.okio:okio:1.13.0 (1 constraints: 7f0cb509) io.undertow:undertow-core:2.0.17.Final (1 constraints: 54072861) -jakarta.annotation:jakarta.annotation-api:1.3.5 (4 constraints: c93b8593) -jakarta.servlet:jakarta.servlet-api:4.0.4 (9 constraints: e4866913) -jakarta.validation:jakarta.validation-api:2.0.2 (12 constraints: c9bea393) -jakarta.ws.rs:jakarta.ws.rs-api:2.1.6 (11 constraints: 21bc0ae5) +jakarta.annotation:jakarta.annotation-api:2.1.1 (5 constraints: b540d322) +jakarta.inject:jakarta.inject-api:2.0.1 (11 constraints: 25b1a651) +jakarta.servlet:jakarta.servlet-api:5.0.0 (10 constraints: dc94d6f2) +jakarta.validation:jakarta.validation-api:3.0.2 (13 constraints: dacc4b58) +jakarta.ws.rs:jakarta.ws.rs-api:3.0.0 (14 constraints: 22f227c3) net.sf.jopt-simple:jopt-simple:5.0.4 (1 constraints: be0ad6cc) org.apache.commons:commons-math3:3.2 (1 constraints: 5c0a8ab7) -org.checkerframework:checker-qual:3.4.0 (2 constraints: 411a465e) +org.checkerframework:checker-qual:3.22.2 (14 constraints: 5fcb10a5) org.glassfish.hk2:osgi-resource-locator:1.0.3 (2 constraints: 7d23b265) -org.glassfish.hk2.external:jakarta.inject:2.6.1 (11 constraints: 6ab14a97) -org.glassfish.jersey.core:jersey-client:2.31 (4 constraints: 78509cb2) -org.glassfish.jersey.core:jersey-common:2.31 (11 constraints: dfc64234) -org.glassfish.jersey.core:jersey-server:2.31 (9 constraints: dab3c81c) -org.glassfish.jersey.media:jersey-media-jaxb:2.31 (1 constraints: d110c2b2) +org.glassfish.jersey.core:jersey-client:3.0.5 (6 constraints: 5777f3ab) +org.glassfish.jersey.core:jersey-common:3.0.5 (12 constraints: 00e13196) +org.glassfish.jersey.core:jersey-server:3.0.5 (9 constraints: 2bb57cff) org.immutables:value:2.8.8 (1 constraints: 14051536) -org.jboss.logging:jboss-logging:3.3.2.Final (2 constraints: 7022d9d6) +org.jboss.logging:jboss-logging:3.4.1.Final (2 constraints: 7022dbd6) org.jboss.xnio:xnio-api:3.3.8.Final (2 constraints: 6f1a4d45) org.jboss.xnio:xnio-nio:3.3.8.Final (1 constraints: c40da530) org.openjdk.jmh:jmh-core:1.35 (2 constraints: f315f3d8) org.openjdk.jmh:jmh-generator-annprocess:1.35 (1 constraints: dd04fa30) -org.slf4j:slf4j-api:1.7.32 (26 constraints: e77b6078) +org.slf4j:slf4j-api:2.0.0-alpha7 (31 constraints: aaeb4da6) [Test dependencies] -ch.qos.logback:logback-access:1.2.3 (1 constraints: b41148e2) -ch.qos.logback:logback-classic:1.2.11 (6 constraints: f3510cba) -ch.qos.logback:logback-core:1.2.11 (4 constraints: fc393f39) -com.fasterxml:classmate:1.5.1 (3 constraints: 8630e25a) -com.fasterxml.jackson.core:jackson-annotations:2.13.3 (16 constraints: 0e0d1e16) -com.fasterxml.jackson.core:jackson-core:2.13.3 (16 constraints: 114e2887) -com.fasterxml.jackson.core:jackson-databind:2.13.3 (25 constraints: dfe51a18) +ch.qos.logback:logback-access:1.3.0-alpha16 (1 constraints: 4c14097c) +ch.qos.logback:logback-classic:1.3.0-alpha16 (7 constraints: ae6d4618) +ch.qos.logback:logback-core:1.3.0-alpha16 (5 constraints: 9b54f5eb) +com.fasterxml:classmate:1.5.1 (3 constraints: 8530e55a) +com.fasterxml.jackson.core:jackson-annotations:2.13.3 (17 constraints: b91f58a4) +com.fasterxml.jackson.core:jackson-core:2.13.3 (19 constraints: d2890ead) +com.fasterxml.jackson.core:jackson-databind:2.13.3 (27 constraints: ea14e7c8) com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.13.3 (1 constraints: 7d1c9aa4) com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.13.3 (1 constraints: 7d1c9aa4) -com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.3 (2 constraints: 79165a04) -com.fasterxml.jackson.datatype:jackson-datatype-guava:2.13.3 (3 constraints: f2391c25) -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.3 (2 constraints: 2d2b96af) -com.fasterxml.jackson.datatype:jackson-datatype-joda:2.13.3 (2 constraints: 2d2b96af) -com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.3 (2 constraints: 2d2b96af) -com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:2.13.3 (1 constraints: 7817653d) -com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.13.3 (2 constraints: 1f1d0309) -com.fasterxml.jackson.module:jackson-module-afterburner:2.13.3 (2 constraints: 492b29b6) -com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.13.3 (1 constraints: 7817653d) -com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.3 (1 constraints: b10e595e) -com.github.ben-manes.caffeine:caffeine:2.8.4 (4 constraints: 633c8aa1) +com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.3 (2 constraints: 7b166204) +com.fasterxml.jackson.datatype:jackson-datatype-guava:2.13.3 (3 constraints: f6398025) +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.3 (2 constraints: 2f2b9eaf) +com.fasterxml.jackson.datatype:jackson-datatype-joda:2.13.3 (1 constraints: 7d1c9aa4) +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.3 (2 constraints: 2f2b9eaf) +com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-base:2.13.3 (1 constraints: 091bbe44) +com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-json-provider:2.13.3 (2 constraints: 231d6709) +com.fasterxml.jackson.module:jackson-module-afterburner:2.13.3 (1 constraints: 991c95a6) +com.fasterxml.jackson.module:jackson-module-blackbird:2.13.3 (1 constraints: b30e615e) +com.fasterxml.jackson.module:jackson-module-jakarta-xmlbind-annotations:2.13.3 (1 constraints: 091bbe44) +com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.3 (1 constraints: b30e615e) +com.github.ben-manes.caffeine:caffeine:3.1.1 (4 constraints: 3f3caa98) com.google.code.findbugs:annotations:3.0.1 (1 constraints: 9e0aafc3) -com.helger:profiler:1.1.1 (1 constraints: e21053b8) +com.helger:profiler:1.1.1 (1 constraints: ed130e59) com.palantir.conjure.java.runtime:conjure-java-jackson-optimizations:7.33.0 (1 constraints: 831cbfa4) com.palantir.conjure.java.runtime:conjure-java-jackson-serialization:7.33.0 (1 constraints: 3f055e3b) com.palantir.safe-logging:preconditions-assertj:1.25.0 (1 constraints: 3c05413b) -com.spotify.dataenum:dataenum:1.4.1 (1 constraints: 0805fd35) -io.dropwizard:dropwizard-configuration:2.0.10 (2 constraints: 2e1c3dc0) -io.dropwizard:dropwizard-core:2.0.10 (1 constraints: c20ece5f) -io.dropwizard:dropwizard-jackson:2.0.10 (8 constraints: f5786d98) -io.dropwizard:dropwizard-jersey:2.0.10 (2 constraints: 2e1c3dc0) -io.dropwizard:dropwizard-jetty:2.0.10 (2 constraints: 2e1c3dc0) -io.dropwizard:dropwizard-lifecycle:2.0.10 (3 constraints: e82a0ebe) -io.dropwizard:dropwizard-logging:2.0.10 (5 constraints: 564a6f76) -io.dropwizard:dropwizard-metrics:2.0.10 (1 constraints: 6d0d992c) -io.dropwizard:dropwizard-request-logging:2.0.10 (1 constraints: 6d0d992c) -io.dropwizard:dropwizard-servlets:2.0.10 (2 constraints: 2e1c3dc0) -io.dropwizard:dropwizard-testing:2.0.10 (1 constraints: 35052b3b) -io.dropwizard:dropwizard-util:2.0.10 (12 constraints: 3db6e12c) -io.dropwizard:dropwizard-validation:2.0.10 (8 constraints: f5786d98) -io.dropwizard.logback:logback-throttling-appender:1.1.0 (1 constraints: 7a0ece4f) -io.dropwizard.metrics:metrics-annotation:4.1.9 (3 constraints: eb2d5b17) -io.dropwizard.metrics:metrics-core:4.1.9 (14 constraints: bed295ec) -io.dropwizard.metrics:metrics-healthchecks:4.1.9 (3 constraints: d02c5068) -io.dropwizard.metrics:metrics-jersey2:4.1.9 (1 constraints: 310e1d40) -io.dropwizard.metrics:metrics-jetty9:4.1.9 (1 constraints: 480d411f) -io.dropwizard.metrics:metrics-jmx:4.1.9 (1 constraints: 480d411f) -io.dropwizard.metrics:metrics-json:4.1.9 (1 constraints: ed106ab8) -io.dropwizard.metrics:metrics-jvm:4.1.9 (2 constraints: 341ee147) -io.dropwizard.metrics:metrics-logback:4.1.9 (1 constraints: 860ee64f) -io.dropwizard.metrics:metrics-servlets:4.1.9 (1 constraints: 480d411f) +com.sun.activation:jakarta.activation:2.0.1 (1 constraints: 801dd0e8) +io.dropwizard:dropwizard-configuration:4.0.0-beta.2 (2 constraints: 22205f28) +io.dropwizard:dropwizard-core:4.0.0-beta.2 (1 constraints: bc101bc0) +io.dropwizard:dropwizard-health:4.0.0-beta.2 (1 constraints: 670fe884) +io.dropwizard:dropwizard-jackson:4.0.0-beta.2 (9 constraints: f89845bf) +io.dropwizard:dropwizard-jersey:4.0.0-beta.2 (3 constraints: 55300eb0) +io.dropwizard:dropwizard-jetty:4.0.0-beta.2 (3 constraints: 55300eb0) +io.dropwizard:dropwizard-lifecycle:4.0.0-beta.2 (4 constraints: 0941817e) +io.dropwizard:dropwizard-logging:4.0.0-beta.2 (5 constraints: 3854e38c) +io.dropwizard:dropwizard-metrics:4.0.0-beta.2 (1 constraints: 670fe884) +io.dropwizard:dropwizard-request-logging:4.0.0-beta.2 (1 constraints: 670fe884) +io.dropwizard:dropwizard-servlets:4.0.0-beta.2 (2 constraints: 22205f28) +io.dropwizard:dropwizard-testing:4.0.0-beta.2 (1 constraints: 2f072a62) +io.dropwizard:dropwizard-util:4.0.0-beta.2 (11 constraints: 19b757d2) +io.dropwizard:dropwizard-validation:4.0.0-beta.2 (8 constraints: c588ef2e) +io.dropwizard.logback:logback-throttling-appender:1.1.9 (1 constraints: 830ed74f) +io.dropwizard.metrics:metrics-annotation:4.2.10 (3 constraints: 672e4f88) +io.dropwizard.metrics:metrics-core:4.2.10 (17 constraints: c607beef) +io.dropwizard.metrics:metrics-healthchecks:4.2.10 (4 constraints: 933e1342) +io.dropwizard.metrics:metrics-jakarta-servlets:4.2.10 (1 constraints: 710dad2c) +io.dropwizard.metrics:metrics-jersey3:4.2.10 (1 constraints: 5a0e724e) +io.dropwizard.metrics:metrics-jetty11:4.2.10 (2 constraints: 681b7984) +io.dropwizard.metrics:metrics-jmx:4.2.10 (1 constraints: 710dad2c) +io.dropwizard.metrics:metrics-json:4.2.10 (1 constraints: 2114416d) +io.dropwizard.metrics:metrics-jvm:4.2.10 (2 constraints: 91219b8a) +io.dropwizard.metrics:metrics-logback:4.2.10 (1 constraints: af0e905e) io.zipkin.java:zipkin:1.13.1 (1 constraints: 3805333b) -jakarta.activation:jakarta.activation-api:1.2.2 (3 constraints: 4d37e9b5) -jakarta.xml.bind:jakarta.xml.bind-api:2.3.3 (2 constraints: c7279e00) -javax.servlet:javax.servlet-api:3.1.0 (1 constraints: 830dcc28) -joda-time:joda-time:2.10.8 (2 constraints: 892485cd) -junit:junit:4.13.2 (4 constraints: 1053d1ae) +jakarta.activation:jakarta.activation-api:2.1.0 (2 constraints: 1d1e9080) +jakarta.el:jakarta.el-api:4.0.0 (1 constraints: ed0a74d1) +jakarta.xml.bind:jakarta.xml.bind-api:4.0.0 (3 constraints: 1b46dd11) +joda-time:joda-time:2.10.8 (1 constraints: 2e16acf1) +junit:junit:4.13.2 (4 constraints: d05394ba) net.bytebuddy:byte-buddy:1.12.10 (2 constraints: e9163f66) net.bytebuddy:byte-buddy-agent:1.12.10 (1 constraints: 6f0ba8e9) net.jcip:jcip-annotations:1.0 (1 constraints: 560ff165) -net.sourceforge.argparse4j:argparse4j:0.8.1 (2 constraints: da1b0490) +net.sourceforge.argparse4j:argparse4j:0.9.0 (2 constraints: da1b0890) org.apache-extras.beanshell:bsh:2.0b6 (1 constraints: ac07626b) -org.apache.commons:commons-lang3:3.10 (4 constraints: 4b373a47) -org.apache.commons:commons-text:1.8 (1 constraints: b4102e9b) +org.apache.commons:commons-lang3:3.11 (1 constraints: 990dd426) +org.apache.commons:commons-text:1.9 (1 constraints: b5102f9b) org.apiguardian:apiguardian-api:1.1.2 (6 constraints: 896455cc) org.assertj:assertj-core:3.23.1 (2 constraints: 9619aade) -org.eclipse.jetty:jetty-continuation:9.4.29.v20200521 (1 constraints: d81018f8) -org.eclipse.jetty:jetty-http:9.4.29.v20200521 (4 constraints: 2b459ddb) -org.eclipse.jetty:jetty-io:9.4.29.v20200521 (6 constraints: c5611794) -org.eclipse.jetty:jetty-security:9.4.29.v20200521 (3 constraints: 4e3064e7) -org.eclipse.jetty:jetty-server:9.4.29.v20200521 (7 constraints: eb79b5b1) -org.eclipse.jetty:jetty-servlet:9.4.29.v20200521 (2 constraints: ea1f3da9) -org.eclipse.jetty:jetty-servlets:9.4.29.v20200521 (1 constraints: 39109bd7) -org.eclipse.jetty:jetty-util:9.4.29.v20200521 (8 constraints: e3842031) +org.derive4j:derive4j-annotation:1.1.1 (1 constraints: 0505f435) +org.eclipse.jetty:jetty-http:11.0.11 (5 constraints: 0e4d1aa2) +org.eclipse.jetty:jetty-io:11.0.11 (7 constraints: 80656419) +org.eclipse.jetty:jetty-security:11.0.11 (3 constraints: 122a1f98) +org.eclipse.jetty:jetty-server:11.0.11 (8 constraints: c979200f) +org.eclipse.jetty:jetty-servlet:11.0.11 (2 constraints: c21bbdb4) +org.eclipse.jetty:jetty-servlets:11.0.11 (1 constraints: 250e414c) +org.eclipse.jetty:jetty-util:11.0.11 (10 constraints: e09293f8) +org.eclipse.jetty.toolchain:jetty-jakarta-servlet-api:5.0.2 (1 constraints: 860dd528) org.eclipse.jetty.toolchain.setuid:jetty-setuid-java:1.0.4 (1 constraints: 3f0d2a1f) -org.glassfish:jakarta.el:3.0.3 (2 constraints: bf231f5c) -org.glassfish.hk2:hk2-api:2.6.1 (2 constraints: 991afc66) -org.glassfish.hk2:hk2-locator:2.6.1 (1 constraints: 4410e0ad) -org.glassfish.hk2:hk2-utils:2.6.1 (2 constraints: 21173277) -org.glassfish.hk2.external:aopalliance-repackaged:2.6.1 (2 constraints: 21173277) -org.glassfish.jersey.containers:jersey-container-servlet:2.31 (1 constraints: fb0deb31) -org.glassfish.jersey.containers:jersey-container-servlet-core:2.31 (4 constraints: f84d5af6) -org.glassfish.jersey.ext:jersey-bean-validation:2.31 (1 constraints: 120df811) -org.glassfish.jersey.ext:jersey-metainf-services:2.31 (1 constraints: fb0deb31) -org.glassfish.jersey.inject:jersey-hk2:2.31 (1 constraints: fb0deb31) -org.glassfish.jersey.test-framework:jersey-test-framework-core:2.31 (2 constraints: ae31c038) -org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-inmemory:2.31 (1 constraints: 670e8342) +org.glassfish:jakarta.el:4.0.2 (2 constraints: bf23275c) +org.glassfish.grizzly:connection-pool:3.0.1 (1 constraints: 0e182d4b) +org.glassfish.grizzly:grizzly-framework:3.0.1 (3 constraints: aa317ad4) +org.glassfish.grizzly:grizzly-http:3.0.1 (1 constraints: db1119e3) +org.glassfish.grizzly:grizzly-http-client:1.16 (1 constraints: e4172133) +org.glassfish.grizzly:grizzly-websockets:3.0.1 (1 constraints: 0e182d4b) +org.glassfish.hk2:hk2-api:3.0.3 (2 constraints: 931a7466) +org.glassfish.hk2:hk2-locator:3.0.3 (1 constraints: 4110d5ad) +org.glassfish.hk2:hk2-utils:3.0.3 (2 constraints: 1b17aa76) +org.glassfish.hk2.external:aopalliance-repackaged:3.0.3 (2 constraints: 1b17aa76) +org.glassfish.jersey.connectors:jersey-grizzly-connector:3.0.5 (1 constraints: 970e1551) +org.glassfish.jersey.containers:jersey-container-servlet:3.0.5 (1 constraints: 2b0e1140) +org.glassfish.jersey.containers:jersey-container-servlet-core:3.0.5 (4 constraints: b84e85eb) +org.glassfish.jersey.ext:jersey-bean-validation:3.0.5 (1 constraints: 420d351f) +org.glassfish.jersey.ext:jersey-metainf-services:3.0.5 (1 constraints: 2b0e1140) +org.glassfish.jersey.inject:jersey-hk2:3.0.5 (1 constraints: 2b0e1140) +org.glassfish.jersey.media:jersey-media-jaxb:3.0.5 (1 constraints: 0d1a5ce4) +org.glassfish.jersey.test-framework:jersey-test-framework-core:3.0.5 (2 constraints: 0e32cb8a) +org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-inmemory:3.0.5 (1 constraints: 970e1551) org.hamcrest:hamcrest:2.1 (2 constraints: 8512932d) org.hamcrest:hamcrest-all:1.3 (1 constraints: a8041d2c) org.hamcrest:hamcrest-core:2.1 (2 constraints: 88126e10) org.hamcrest:hamcrest-library:2.1 (1 constraints: 1507415c) -org.hibernate.validator:hibernate-validator:6.1.5.Final (4 constraints: 9b4747ce) -org.javassist:javassist:3.27.0-GA (2 constraints: 3d20076d) +org.hibernate.validator:hibernate-validator:7.0.4.Final (4 constraints: 9747e7cc) +org.javassist:javassist:3.29.0-GA (2 constraints: 42208b6d) org.jmock:jmock:2.12.0 (1 constraints: 3705353b) org.jmock:jmock-testjar:2.12.0 (1 constraints: a507a272) org.junit.jupiter:junit-jupiter:5.9.0 (1 constraints: 10051f36) -org.junit.jupiter:junit-jupiter-api:5.9.0 (4 constraints: 823413b9) +org.junit.jupiter:junit-jupiter-api:5.9.0 (5 constraints: 4b4361b2) org.junit.jupiter:junit-jupiter-engine:5.9.0 (1 constraints: 0b0ee03b) org.junit.jupiter:junit-jupiter-params:5.9.0 (1 constraints: 0b0ee03b) org.junit.platform:junit-platform-commons:1.9.0 (2 constraints: db20dc4a) org.junit.platform:junit-platform-engine:1.9.0 (2 constraints: 2921a573) org.junit.vintage:junit-vintage-engine:5.9.0 (1 constraints: 10051f36) -org.mockito:mockito-core:4.6.1 (1 constraints: 0d051236) +org.mockito:mockito-core:4.6.1 (2 constraints: d213aa65) +org.mockito:mockito-junit-jupiter:4.6.1 (1 constraints: 0d051236) org.objenesis:objenesis:3.2 (1 constraints: b10a13bd) org.opentest4j:opentest4j:1.2.0 (2 constraints: cd205b49) org.ow2.asm:asm:7.1 (1 constraints: 1a07505c) -org.slf4j:jcl-over-slf4j:1.7.30 (1 constraints: b30e965e) -org.slf4j:jul-to-slf4j:1.7.30 (1 constraints: b30e965e) -org.slf4j:log4j-over-slf4j:1.7.30 (1 constraints: b30e965e) +org.slf4j:jcl-over-slf4j:2.0.0-alpha7 (1 constraints: e410b4be) +org.slf4j:jul-to-slf4j:2.0.0-alpha7 (1 constraints: e410b4be) +org.slf4j:log4j-over-slf4j:2.0.0-alpha7 (1 constraints: e410b4be) org.yaml:snakeyaml:1.30 (1 constraints: 6c17f527) diff --git a/versions.props b/versions.props index 39b68c481..60a8e1a24 100644 --- a/versions.props +++ b/versions.props @@ -5,13 +5,18 @@ com.fasterxml.jackson.*:* = 2.12.3 com.google.guava:guava = 28.0-jre com.palantir.safe-logging:* = 1.18.0 com.squareup.okhttp3:okhttp = 3.9.0 -io.dropwizard:dropwizard-* = 2.0.10 +io.dropwizard:dropwizard-* = 4.0.0-beta.2 io.undertow:undertow-core = 2.0.17.Final io.zipkin.java:* = 1.13.1 -jakarta.servlet:jakarta.servlet-api = 4.0.4 -jakarta.ws.rs:jakarta.ws.rs-api = 2.1.6 -org.glassfish.jersey.*:* = 2.22.2 +jakarta.servlet:jakarta.servlet-api = 5.0.0 +jakarta.ws.rs:jakarta.ws.rs-api = 3.0.0 +org.glassfish.jersey.*:* = 3.0.5 org.slf4j:slf4j-api = 1.7.12 +jakarta.annotation:jakarta.annotation-api = 2.1.1 + +# legacy javax versions +javax.ws.rs:javax.ws.rs-api = 2.1.1 +javax.servlet:javax.servlet-api = 4.0.1 # dependency-upgrader:ON com.fasterxml.jackson.core:jackson-databind = 2.13.3 @@ -21,11 +26,11 @@ org.hamcrest:hamcrest-* = 1.3 org.immutables:value = 2.8.8 org.openjdk.jmh:* = 1.35 org.jmock:jmock = 2.12.0 -org.mockito:mockito-core = 4.6.1 +org.mockito:* = 4.6.1 ch.qos.logback:logback-classic = 1.2.11 org.apache.logging.log4j:log4j-slf4j-impl = 2.18.0 org.junit.jupiter:* = 5.9.0 org.junit.vintage:* = 5.9.0 com.uber.nullaway:nullaway = 0.9.9 -com.spotify.dataenum:* = 1.4.1 +org.derive4j:* = 1.1.1 com.palantir.conjure.java.runtime:* = 7.33.0