diff --git a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/ClientEndpointIndexer.java b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/ClientEndpointIndexer.java index 971df78e562ac..cedfbf44218ad 100644 --- a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/ClientEndpointIndexer.java +++ b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/ClientEndpointIndexer.java @@ -44,11 +44,13 @@ public class ClientEndpointIndexer private final String[] defaultProduces; private final String[] defaultProducesNegotiated; + private final boolean smartDefaultProduces; - ClientEndpointIndexer(Builder builder, String defaultProduces) { + ClientEndpointIndexer(Builder builder, String defaultProduces, boolean smartDefaultProduces) { super(builder); this.defaultProduces = new String[] { defaultProduces }; this.defaultProducesNegotiated = new String[] { defaultProduces, MediaType.WILDCARD }; + this.smartDefaultProduces = smartDefaultProduces; } public MaybeRestClientInterface createClientProxy(ClassInfo classInfo, @@ -125,10 +127,14 @@ elementType, toClassName(paramType, currentClassInfo, actualEndpointInfo, index) @Override protected String[] applyAdditionalDefaults(Type nonAsyncReturnType) { - if (config.isSingleDefaultProduces()) { - return defaultProduces; + if (smartDefaultProduces) { + return super.applyAdditionalDefaults(nonAsyncReturnType); } else { - return defaultProducesNegotiated; + if (config.isSingleDefaultProduces()) { + return defaultProduces; + } else { + return defaultProducesNegotiated; + } } } @@ -166,15 +172,21 @@ public static class ClientIndexedParam extends IndexedParameter { private String defaultProduces = MediaType.TEXT_PLAIN; + private boolean smartDefaultProduces = true; public Builder setDefaultProduces(String defaultProduces) { this.defaultProduces = defaultProduces; return this; } + public Builder setSmartDefaultProduces(boolean smartDefaultProduces) { + this.smartDefaultProduces = smartDefaultProduces; + return this; + } + @Override public ClientEndpointIndexer build() { - return new ClientEndpointIndexer(this, defaultProduces); + return new ClientEndpointIndexer(this, defaultProduces, smartDefaultProduces); } } } diff --git a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java index 4ebd6d3c9cfb1..3d1d3ee46949f 100644 --- a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java +++ b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java @@ -159,7 +159,8 @@ void setupClientProxies(JaxrsClientReactiveRecorder recorder, BuildProducer generatedClassBuildItemBuildProducer, BuildProducer bytecodeTransformerBuildItemBuildProducer, List defaultConsumes, - List defaultProduces) { + List defaultProduces, + List disableSmartDefaultProduces) { String defaultConsumesType = defaultMediaType(defaultConsumes, MediaType.APPLICATION_OCTET_STREAM); String defaultProducesType = defaultMediaType(defaultProduces, MediaType.TEXT_PLAIN); @@ -194,6 +195,7 @@ void setupClientProxies(JaxrsClientReactiveRecorder recorder, .setDefaultBlocking(applicationResultBuildItem.getResult().isBlocking()) .setHasRuntimeConverters(false) .setDefaultProduces(defaultProducesType) + .setSmartDefaultProduces(disableSmartDefaultProduces.isEmpty()) .build(); Map>> clientImplementations = new HashMap<>(); diff --git a/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/RestClientDisableSmartDefaultProduces.java b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/RestClientDisableSmartDefaultProduces.java new file mode 100644 index 0000000000000..ee0d6b162bfff --- /dev/null +++ b/extensions/resteasy-reactive/jaxrs-client-reactive/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/RestClientDisableSmartDefaultProduces.java @@ -0,0 +1,12 @@ +package io.quarkus.jaxrs.client.reactive.deployment; + +import io.quarkus.builder.item.MultiBuildItem; + +/** + * By default, RESTEasy Reactive uses text/plain content type for String values + * and application/json for everything else. + * MicroProfile Rest Client spec requires the implementations to always default to application/json. + * This build item disables the "smart" behavior of RESTEasy Reactive to comply to the spec + */ +public final class RestClientDisableSmartDefaultProduces extends MultiBuildItem { +} diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java index acd07d90a6ac7..8894a15c756b1 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/RestClientReactiveProcessor.java @@ -65,6 +65,7 @@ import io.quarkus.jaxrs.client.reactive.deployment.JaxrsClientReactiveEnricherBuildItem; import io.quarkus.jaxrs.client.reactive.deployment.RestClientDefaultConsumesBuildItem; import io.quarkus.jaxrs.client.reactive.deployment.RestClientDefaultProducesBuildItem; +import io.quarkus.jaxrs.client.reactive.deployment.RestClientDisableSmartDefaultProduces; import io.quarkus.rest.client.reactive.runtime.AnnotationRegisteredProviders; import io.quarkus.rest.client.reactive.runtime.HeaderCapturingServerFilter; import io.quarkus.rest.client.reactive.runtime.HeaderContainer; @@ -98,9 +99,14 @@ ExtensionSslNativeSupportBuildItem activateSslNativeSupport() { @BuildStep void setUpDefaultMediaType(BuildProducer consumes, - BuildProducer produces) { + BuildProducer produces, + BuildProducer disableSmartProduces, + RestClientReactiveConfig config) { consumes.produce(new RestClientDefaultConsumesBuildItem(MediaType.APPLICATION_JSON, 10)); produces.produce(new RestClientDefaultProducesBuildItem(MediaType.APPLICATION_JSON, 10)); + if (config.disableSmartProduces) { + disableSmartProduces.produce(new RestClientDisableSmartDefaultProduces()); + } } @BuildStep diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicMpRestClientTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicRestClientTest.java similarity index 97% rename from extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicMpRestClientTest.java rename to extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicRestClientTest.java index 7703a3e52caf6..3e332a87d602b 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicMpRestClientTest.java +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/BasicRestClientTest.java @@ -18,7 +18,7 @@ import io.quarkus.arc.Arc; import io.quarkus.test.QuarkusUnitTest; -public class BasicMpRestClientTest { +public class BasicRestClientTest { @RegisterExtension static final QuarkusUnitTest TEST = new QuarkusUnitTest() .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloClient2.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloClient2.java index 4834c5cbb66a6..ab81bc507fb49 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloClient2.java +++ b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/HelloClient2.java @@ -3,7 +3,6 @@ import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; -import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @@ -11,7 +10,6 @@ @RegisterRestClient(configKey = "hello2") public interface HelloClient2 { @POST - @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.TEXT_PLAIN) @Path("/") String echo(String name); diff --git a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientReactiveConfig.java b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientReactiveConfig.java index 642e05c388972..4dd42dd348918 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientReactiveConfig.java +++ b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientReactiveConfig.java @@ -8,8 +8,18 @@ public class RestClientReactiveConfig { /** - * Default scope for MicroProfile Rest Client. Use `javax.enterprise.context.Dependent` for spec-compliant behavior + * Default scope for Rest Client Reactive. Use `javax.enterprise.context.Dependent` for spec-compliant behavior */ @ConfigItem(name = "scope", defaultValue = "javax.enterprise.context.ApplicationScoped") public String scope; + + /** + * By default, RESTEasy Reactive uses text/plain content type for String values + * and application/json for everything else. + * + * MicroProfile Rest Client spec requires the implementations to always default to application/json. + * This build item disables the "smart" behavior of RESTEasy Reactive to comply to the spec + */ + @ConfigItem(name = "disable-smart-produces", defaultValue = "false") + public boolean disableSmartProduces; } diff --git a/tcks/microprofile-rest-client-reactive/pom.xml b/tcks/microprofile-rest-client-reactive/pom.xml index 56597e726a5d6..c8719dbcadd69 100644 --- a/tcks/microprofile-rest-client-reactive/pom.xml +++ b/tcks/microprofile-rest-client-reactive/pom.xml @@ -24,6 +24,7 @@ true false javax.enterprise.context.Dependent + true true ${wiremock.server.port}