From 3c4be700e8d8738128324c4f2d020d538c0ba0d9 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Thu, 6 Nov 2025 13:34:49 +0200 Subject: [PATCH] Introduce build items for JAX-RS client filters Closes: #50888 --- .../RestClientReactiveProcessor.java | 47 ++++++++++++++----- .../spi/ClientRequestFilterBuildItem.java | 19 ++++++++ .../spi/ClientResponseFilterBuildItem.java | 19 ++++++++ 3 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 extensions/resteasy-reactive/rest-client/spi-deployment/src/main/java/io/quarkus/rest/client/reactive/spi/ClientRequestFilterBuildItem.java create mode 100644 extensions/resteasy-reactive/rest-client/spi-deployment/src/main/java/io/quarkus/rest/client/reactive/spi/ClientResponseFilterBuildItem.java diff --git a/extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java b/extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java index d4123996465e1..0781113ffc1d2 100644 --- a/extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java +++ b/extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java @@ -105,6 +105,8 @@ import io.quarkus.rest.client.reactive.runtime.RestClientReactiveCDIWrapperBase; import io.quarkus.rest.client.reactive.runtime.RestClientReactiveConfig; import io.quarkus.rest.client.reactive.runtime.RestClientRecorder; +import io.quarkus.rest.client.reactive.spi.ClientRequestFilterBuildItem; +import io.quarkus.rest.client.reactive.spi.ClientResponseFilterBuildItem; import io.quarkus.rest.client.reactive.spi.RestClientAnnotationsTransformerBuildItem; import io.quarkus.restclient.config.RegisteredRestClient; import io.quarkus.restclient.config.RestClientsBuildTimeConfig; @@ -281,6 +283,8 @@ public void registerProvidersInstances(CombinedIndexBuildItem indexBuildItem, void registerProvidersFromAnnotations(CombinedIndexBuildItem indexBuildItem, List registerProviderAnnotationInstances, List annotationsToRegisterIntoClientContext, + List clientRequestFilters, + List clientResponseFilters, BuildProducer generatedBeansProducer, BuildProducer generatedClassesProducer, BuildProducer unremovableBeansProducer, @@ -325,20 +329,22 @@ void registerProvidersFromAnnotations(CombinedIndexBuildItem indexBuildItem, continue; } - DotName providerDotName = providerClass.name(); - int priority = getAnnotatedPriority(index, providerDotName.toString(), Priorities.USER); - - constructor.invokeVirtualMethod( - MethodDescriptor.ofMethod(AnnotationRegisteredProviders.class, "addGlobalProvider", - void.class, Class.class, - int.class), - constructor.getThis(), constructor.loadClassFromTCCL(providerDotName.toString()), - constructor.load(priority)); + registerGlobalProvider(providerClass.name(), index, constructor, reflectiveClassesProducer); + } + } - // when the server is not included, providers are not automatically registered for reflection, - // so we need to always do it for the client to be on the safe side - reflectiveClassesProducer.produce(ReflectiveClassBuildItem.builder(providerDotName.toString()).build()); + Set providersFromBuildItems = new HashSet<>(); + providersFromBuildItems.addAll(clientRequestFilters.stream().map(ClientRequestFilterBuildItem::getClassName) + .map(DotName::createSimple).collect( + Collectors.toSet())); + providersFromBuildItems.addAll(clientResponseFilters.stream().map(ClientResponseFilterBuildItem::getClassName) + .map(DotName::createSimple).collect( + Collectors.toSet())); + if (!providersFromBuildItems.isEmpty()) { + for (DotName dotName : providersFromBuildItems) { + registerGlobalProvider(dotName, index, constructor, reflectiveClassesProducer); } + unremovableBeansProducer.produce(UnremovableBeanBuildItem.beanTypes(providersFromBuildItems)); } MultivaluedMap generatedProviders = new QuarkusMultivaluedHashMap<>(); @@ -361,6 +367,23 @@ void registerProvidersFromAnnotations(CombinedIndexBuildItem indexBuildItem, unremovableBeansProducer.produce(UnremovableBeanBuildItem.beanClassNames(annotationRegisteredProvidersImpl)); } + private void registerGlobalProvider(DotName providerClassName, + IndexView index, MethodCreator methodCreator, + BuildProducer reflectiveClassesProducer) { + int priority = getAnnotatedPriority(index, providerClassName.toString(), Priorities.USER); + + methodCreator.invokeVirtualMethod( + MethodDescriptor.ofMethod(AnnotationRegisteredProviders.class, "addGlobalProvider", + void.class, Class.class, + int.class), + methodCreator.getThis(), methodCreator.loadClassFromTCCL(providerClassName.toString()), + methodCreator.load(priority)); + + // when the server is not included, providers are not automatically registered for reflection, + // so we need to always do it for the client to be on the safe side + reflectiveClassesProducer.produce(ReflectiveClassBuildItem.builder(providerClassName.toString()).build()); + } + @BuildStep AdditionalBeanBuildItem registerProviderBeans(CombinedIndexBuildItem combinedIndex) { IndexView index = combinedIndex.getIndex(); diff --git a/extensions/resteasy-reactive/rest-client/spi-deployment/src/main/java/io/quarkus/rest/client/reactive/spi/ClientRequestFilterBuildItem.java b/extensions/resteasy-reactive/rest-client/spi-deployment/src/main/java/io/quarkus/rest/client/reactive/spi/ClientRequestFilterBuildItem.java new file mode 100644 index 0000000000000..f80a0f4026a41 --- /dev/null +++ b/extensions/resteasy-reactive/rest-client/spi-deployment/src/main/java/io/quarkus/rest/client/reactive/spi/ClientRequestFilterBuildItem.java @@ -0,0 +1,19 @@ +package io.quarkus.rest.client.reactive.spi; + +import io.quarkus.builder.item.MultiBuildItem; + +/** + * Used to make a register a global {@link jakarta.ws.rs.client.ClientRequestFilter} + */ +public final class ClientRequestFilterBuildItem extends MultiBuildItem { + + private final String className; + + public ClientRequestFilterBuildItem(String className) { + this.className = className; + } + + public String getClassName() { + return className; + } +} diff --git a/extensions/resteasy-reactive/rest-client/spi-deployment/src/main/java/io/quarkus/rest/client/reactive/spi/ClientResponseFilterBuildItem.java b/extensions/resteasy-reactive/rest-client/spi-deployment/src/main/java/io/quarkus/rest/client/reactive/spi/ClientResponseFilterBuildItem.java new file mode 100644 index 0000000000000..167d6587dc328 --- /dev/null +++ b/extensions/resteasy-reactive/rest-client/spi-deployment/src/main/java/io/quarkus/rest/client/reactive/spi/ClientResponseFilterBuildItem.java @@ -0,0 +1,19 @@ +package io.quarkus.rest.client.reactive.spi; + +import io.quarkus.builder.item.MultiBuildItem; + +/** + * Used to make a register a global {@link jakarta.ws.rs.client.ClientResponseFilter} + */ +public final class ClientResponseFilterBuildItem extends MultiBuildItem { + + private final String className; + + public ClientResponseFilterBuildItem(String className) { + this.className = className; + } + + public String getClassName() { + return className; + } +}