From 8735ad1080938c76962745f1f255a28c1d7cf0e8 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Mon, 10 Jan 2022 15:12:43 +0200 Subject: [PATCH] Make copying of Vertx context data conditional In order to avoid negatively affecting RESTEasy Reactive performance just to serve very specific use cases, we introduce a way to conditionally control when the current Vertx request context data needs to be copied into the connection context Follow up off: #22671 --- .../deployment/OpenTelemetryProcessor.java | 6 ++++++ .../deployment/ResteasyReactiveProcessor.java | 7 +++++-- ...QuarkusResteasyReactiveRequestContext.java | 7 +++++-- .../runtime/ResteasyReactiveRecorder.java | 6 ++++-- .../CopyVertxContextDataBuildItem.java | 20 +++++++++++++++++++ .../vertx/VertxRequestContextFactory.java | 3 ++- .../VertxResteasyReactiveRequestContext.java | 16 ++++++++++++--- 7 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 extensions/vertx/deployment/src/main/java/io/quarkus/vertx/deployment/CopyVertxContextDataBuildItem.java diff --git a/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java b/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java index f9f45c0fa7cd2..8dacc413feefd 100644 --- a/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java +++ b/extensions/opentelemetry/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java @@ -34,6 +34,7 @@ import io.quarkus.runtime.LaunchMode; import io.quarkus.runtime.RuntimeValue; import io.quarkus.vertx.core.deployment.CoreVertxBuildItem; +import io.quarkus.vertx.deployment.CopyVertxContextDataBuildItem; public class OpenTelemetryProcessor { static class OpenTelemetryEnabled implements BooleanSupplier { @@ -137,6 +138,11 @@ void storeVertxOnContextStorage(OpenTelemetryRecorder recorder, CoreVertxBuildIt recorder.storeVertxOnContextStorage(vertx.getVertx()); } + @BuildStep + CopyVertxContextDataBuildItem copyVertxContextData() { + return new CopyVertxContextDataBuildItem(QuarkusContextStorage.ACTIVE_CONTEXT); + } + public static boolean isClassPresent(String classname) { try { Class.forName(classname, false, Thread.currentThread().getContextClassLoader()); diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java index 698bd0df963b8..fb5e31c7b2123 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveProcessor.java @@ -151,6 +151,7 @@ import io.quarkus.security.AuthenticationCompletionException; import io.quarkus.security.AuthenticationRedirectException; import io.quarkus.security.ForbiddenException; +import io.quarkus.vertx.deployment.CopyVertxContextDataBuildItem; import io.quarkus.vertx.http.deployment.RouteBuildItem; import io.quarkus.vertx.http.runtime.HttpBuildTimeConfig; import io.quarkus.vertx.http.runtime.VertxHttpRecorder; @@ -643,7 +644,8 @@ public void setupDeployment(BeanArchiveIndexBuildItem beanArchiveIndexBuildItem, ParamConverterProvidersBuildItem paramConverterProvidersBuildItem, ContextResolversBuildItem contextResolversBuildItem, ResteasyReactiveServerConfig serverConfig, - LaunchModeBuildItem launchModeBuildItem) + LaunchModeBuildItem launchModeBuildItem, + List copyVertxContextDataBuildItems) throws NoSuchMethodException { if (!resourceScanningResultBuildItem.isPresent()) { @@ -761,7 +763,8 @@ public void setupDeployment(BeanArchiveIndexBuildItem beanArchiveIndexBuildItem, RuntimeValue deployment = recorder.createDeployment(deploymentInfo, beanContainerBuildItem.getValue(), shutdownContext, vertxConfig, requestContextFactoryBuildItem.map(RequestContextFactoryBuildItem::getFactory).orElse(null), - initClassFactory, launchModeBuildItem.getLaunchMode(), servletPresent); + initClassFactory, launchModeBuildItem.getLaunchMode(), servletPresent, + copyVertxContextDataBuildItems.stream().map(CopyVertxContextDataBuildItem::getProperty).collect(toList())); quarkusRestDeploymentBuildItemBuildProducer .produce(new ResteasyReactiveDeploymentBuildItem(deployment, deploymentPath)); diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/QuarkusResteasyReactiveRequestContext.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/QuarkusResteasyReactiveRequestContext.java index 822cc2e5d30e3..2148f9e731c85 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/QuarkusResteasyReactiveRequestContext.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/QuarkusResteasyReactiveRequestContext.java @@ -1,5 +1,7 @@ package io.quarkus.resteasy.reactive.server.runtime; +import java.util.List; + import javax.enterprise.event.Event; import javax.ws.rs.core.SecurityContext; @@ -23,8 +25,9 @@ public class QuarkusResteasyReactiveRequestContext extends VertxResteasyReactive public QuarkusResteasyReactiveRequestContext(Deployment deployment, ProvidersImpl providers, RoutingContext context, ThreadSetupAction requestContext, ServerRestHandler[] handlerChain, ServerRestHandler[] abortHandlerChain, ClassLoader devModeTccl, - CurrentIdentityAssociation currentIdentityAssociation) { - super(deployment, providers, context, requestContext, handlerChain, abortHandlerChain, devModeTccl); + CurrentIdentityAssociation currentIdentityAssociation, List vertxContextPropsToCopy) { + super(deployment, providers, context, requestContext, handlerChain, abortHandlerChain, devModeTccl, + vertxContextPropsToCopy); this.association = currentIdentityAssociation; } diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/ResteasyReactiveRecorder.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/ResteasyReactiveRecorder.java index 0c82fb6dd045b..fe1d9a95287c0 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/ResteasyReactiveRecorder.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/ResteasyReactiveRecorder.java @@ -4,6 +4,7 @@ import java.io.Closeable; import java.lang.reflect.InvocationTargetException; +import java.util.List; import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.function.Function; @@ -73,7 +74,7 @@ public RuntimeValue createDeployment(DeploymentInfo info, ShutdownContext shutdownContext, HttpBuildTimeConfig vertxConfig, RequestContextFactory contextFactory, BeanFactory initClassFactory, - LaunchMode launchMode, boolean servletPresent) { + LaunchMode launchMode, boolean servletPresent, List vertxContextPropsToCopy) { if (servletPresent) { info.setResumeOn404(true); @@ -107,7 +108,8 @@ public ResteasyReactiveRequestContext createContext(Deployment deployment, return new QuarkusResteasyReactiveRequestContext(deployment, providers, (RoutingContext) context, requestContext, handlerChain, - abortHandlerChain, launchMode == LaunchMode.DEVELOPMENT ? tccl : null, currentIdentityAssociation); + abortHandlerChain, launchMode == LaunchMode.DEVELOPMENT ? tccl : null, currentIdentityAssociation, + vertxContextPropsToCopy); } }; diff --git a/extensions/vertx/deployment/src/main/java/io/quarkus/vertx/deployment/CopyVertxContextDataBuildItem.java b/extensions/vertx/deployment/src/main/java/io/quarkus/vertx/deployment/CopyVertxContextDataBuildItem.java new file mode 100644 index 0000000000000..db862551db331 --- /dev/null +++ b/extensions/vertx/deployment/src/main/java/io/quarkus/vertx/deployment/CopyVertxContextDataBuildItem.java @@ -0,0 +1,20 @@ +package io.quarkus.vertx.deployment; + +import io.quarkus.builder.item.MultiBuildItem; + +/** + * Build item which indicates that the current Vertx request context data needs + * to be copied into the connection context + */ +public final class CopyVertxContextDataBuildItem extends MultiBuildItem { + + private final String property; + + public CopyVertxContextDataBuildItem(String property) { + this.property = property; + } + + public String getProperty() { + return property; + } +} diff --git a/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxRequestContextFactory.java b/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxRequestContextFactory.java index 3352eb2967945..699aded446384 100644 --- a/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxRequestContextFactory.java +++ b/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxRequestContextFactory.java @@ -1,6 +1,7 @@ package org.jboss.resteasy.reactive.server.vertx; import io.vertx.ext.web.RoutingContext; +import java.util.Collections; import org.jboss.resteasy.reactive.server.core.Deployment; import org.jboss.resteasy.reactive.server.core.RequestContextFactory; import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext; @@ -14,6 +15,6 @@ public ResteasyReactiveRequestContext createContext(Deployment deployment, ProvidersImpl providers, Object context, ThreadSetupAction requestContext, ServerRestHandler[] handlerChain, ServerRestHandler[] abortHandlerChain) { return new VertxResteasyReactiveRequestContext(deployment, providers, (RoutingContext) context, - requestContext, handlerChain, abortHandlerChain, null); + requestContext, handlerChain, abortHandlerChain, null, Collections.emptyList()); } } diff --git a/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxResteasyReactiveRequestContext.java b/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxResteasyReactiveRequestContext.java index deeff94345c92..0157be3261165 100644 --- a/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxResteasyReactiveRequestContext.java +++ b/independent-projects/resteasy-reactive/server/vertx/src/main/java/org/jboss/resteasy/reactive/server/vertx/VertxResteasyReactiveRequestContext.java @@ -52,7 +52,7 @@ public class VertxResteasyReactiveRequestContext extends ResteasyReactiveRequest public VertxResteasyReactiveRequestContext(Deployment deployment, ProvidersImpl providers, RoutingContext context, ThreadSetupAction requestContext, ServerRestHandler[] handlerChain, ServerRestHandler[] abortHandlerChain, - ClassLoader devModeTccl) { + ClassLoader devModeTccl, List vertxContextPropsToCopy) { super(deployment, providers, requestContext, handlerChain, abortHandlerChain); this.context = context; this.request = context.request(); @@ -61,8 +61,18 @@ public VertxResteasyReactiveRequestContext(Deployment deployment, ProvidersImpl context.addHeadersEndHandler(this); String expect = request.getHeader(HttpHeaderNames.EXPECT); ContextInternal internal = ((ConnectionBase) context.request().connection()).getContext(); - ContextInternal current = (ContextInternal) Vertx.currentContext(); - internal.localContextData().putAll(current.localContextData()); + if (!vertxContextPropsToCopy.isEmpty()) { + ContextInternal current = (ContextInternal) Vertx.currentContext(); + Map internalLocalContextData = internal.localContextData(); + Map currentLocalContextData = current.localContextData(); + for (int i = 0; i < vertxContextPropsToCopy.size(); i++) { + String name = vertxContextPropsToCopy.get(i); + Object value = currentLocalContextData.get(name); + if (value != null) { + internalLocalContextData.put(name, value); + } + } + } if (expect != null && expect.equalsIgnoreCase(CONTINUE)) { continueState = ContinueState.REQUIRED; }