diff --git a/bom/deployment/pom.xml b/bom/deployment/pom.xml index 3b72d5afc0557..234529c3bc892 100644 --- a/bom/deployment/pom.xml +++ b/bom/deployment/pom.xml @@ -236,6 +236,21 @@ quarkus-rest-client-deployment ${project.version} + + io.quarkus + quarkus-rest-client-jackson-deployment + ${project.version} + + + io.quarkus + quarkus-rest-client-jaxb-deployment + ${project.version} + + + io.quarkus + quarkus-rest-client-jsonb-deployment + ${project.version} + io.quarkus quarkus-jaeger-deployment diff --git a/bom/runtime/pom.xml b/bom/runtime/pom.xml index d3c82401b67c3..10d434167fed5 100644 --- a/bom/runtime/pom.xml +++ b/bom/runtime/pom.xml @@ -560,6 +560,21 @@ quarkus-rest-client ${project.version} + + io.quarkus + quarkus-rest-client-jackson + ${project.version} + + + io.quarkus + quarkus-rest-client-jaxb + ${project.version} + + + io.quarkus + quarkus-rest-client-jsonb + ${project.version} + io.quarkus quarkus-resteasy-common diff --git a/core/deployment/src/main/java/io/quarkus/deployment/Capabilities.java b/core/deployment/src/main/java/io/quarkus/deployment/Capabilities.java index 5e75521e1d3f9..62c05858864a1 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/Capabilities.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/Capabilities.java @@ -15,6 +15,8 @@ public final class Capabilities extends SimpleBuildItem { public static final String TRANSACTIONS = "io.quarkus.transactions"; public static final String JACKSON = "io.quarkus.jackson"; public static final String JSONB = "io.quarkus.jsonb"; + public static final String REST_JACKSON = "io.quarkus.rest.jackson"; + public static final String REST_JSONB = "io.quarkus.rest.jsonb"; public static final String RESTEASY_JSON_EXTENSION = "io.quarkus.resteasy-json"; public static final String RESTEASY = "io.quarkus.resteasy"; public static final String JWT = "io.quarkus.jwt"; diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/FeatureBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/FeatureBuildItem.java index f43795633f15b..92da1114320c8 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/builditem/FeatureBuildItem.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/builditem/FeatureBuildItem.java @@ -62,6 +62,9 @@ public final class FeatureBuildItem extends MultiBuildItem { public static final String RESTEASY_MUTINY = "resteasy-mutiny"; public static final String RESTEASY_QUTE = "resteasy-qute"; public static final String REST_CLIENT = "rest-client"; + public static final String REST_CLIENT_JACKSON = "rest-client-jackson"; + public static final String REST_CLIENT_JAXB = "rest-client-jaxb"; + public static final String REST_CLIENT_JSONB = "rest-client-jsonb"; public static final String SCALA = "scala"; public static final String SCHEDULER = "scheduler"; public static final String SECURITY = "security"; diff --git a/extensions/pom.xml b/extensions/pom.xml index 4d6c3ed441682..f7395ba709218 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -51,6 +51,9 @@ resteasy-mutiny resteasy-qute rest-client + rest-client-jackson + rest-client-jsonb + rest-client-jaxb smallrye-openapi-common smallrye-openapi swagger-ui diff --git a/extensions/rest-client-jackson/deployment/pom.xml b/extensions/rest-client-jackson/deployment/pom.xml new file mode 100644 index 0000000000000..d0ba161b61338 --- /dev/null +++ b/extensions/rest-client-jackson/deployment/pom.xml @@ -0,0 +1,64 @@ + + + + quarkus-rest-client-jackson-parent + io.quarkus + 999-SNAPSHOT + ../ + + 4.0.0 + + quarkus-rest-client-jackson-deployment + Quarkus - REST Client - Jackson - Deployment + + + + io.quarkus + quarkus-rest-client-deployment + + + io.quarkus + quarkus-jackson-deployment + + + io.quarkus + quarkus-rest-client-jackson + + + + io.quarkus + quarkus-resteasy-deployment + test + + + io.quarkus + quarkus-junit5-internal + test + + + io.rest-assured + rest-assured + test + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/rest-client-jackson/deployment/src/main/java/io/quarkus/restclient/jackson/deployment/RestClientJacksonProcessor.java b/extensions/rest-client-jackson/deployment/src/main/java/io/quarkus/restclient/jackson/deployment/RestClientJacksonProcessor.java new file mode 100644 index 0000000000000..c2427ea1cda84 --- /dev/null +++ b/extensions/rest-client-jackson/deployment/src/main/java/io/quarkus/restclient/jackson/deployment/RestClientJacksonProcessor.java @@ -0,0 +1,18 @@ +package io.quarkus.restclient.jackson.deployment; + +import io.quarkus.deployment.Capabilities; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.CapabilityBuildItem; +import io.quarkus.deployment.builditem.FeatureBuildItem; + +public class RestClientJacksonProcessor { + + @BuildStep + void build(BuildProducer feature, + BuildProducer capability) { + feature.produce(new FeatureBuildItem(FeatureBuildItem.REST_CLIENT_JACKSON)); + + capability.produce(new CapabilityBuildItem(Capabilities.REST_JACKSON)); + } +} diff --git a/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/ClientResource.java b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/ClientResource.java new file mode 100644 index 0000000000000..f107c8d39c2ce --- /dev/null +++ b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/ClientResource.java @@ -0,0 +1,33 @@ +package io.quarkus.restclient.jackson.deployment; + +import java.time.Month; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@Path("/client") +public class ClientResource { + + @Inject + @RestClient + RestInterface restInterface; + + @GET + @Path("/hello") + public String hello() { + DateDto dateDto = restInterface.get(); + ZonedDateTime zonedDateTime = dateDto.getDate(); + + if (zonedDateTime.getMonth().equals(Month.NOVEMBER) + && zonedDateTime.getZone().equals(ZoneId.of("Europe/London"))) { + return "OK"; + } + + return "INVALID"; + } +} diff --git a/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/DateDto.java b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/DateDto.java new file mode 100644 index 0000000000000..a94d70bb2789e --- /dev/null +++ b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/DateDto.java @@ -0,0 +1,23 @@ +package io.quarkus.restclient.jackson.deployment; + +import java.time.ZonedDateTime; + +public class DateDto { + + private ZonedDateTime date; + + public DateDto() { + } + + public DateDto(ZonedDateTime date) { + this.date = date; + } + + public void setDate(ZonedDateTime date) { + this.date = date; + } + + public ZonedDateTime getDate() { + return date; + } +} diff --git a/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/HelloResource.java b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/HelloResource.java new file mode 100644 index 0000000000000..89bce568ad2d0 --- /dev/null +++ b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/HelloResource.java @@ -0,0 +1,27 @@ +package io.quarkus.restclient.jackson.deployment; + +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +@Produces(MediaType.APPLICATION_JSON) +@Path("/hello") +public class HelloResource { + + @Inject + ObjectMapper objectMapper; + + @GET + public String hello() throws JsonProcessingException { + return objectMapper + .writeValueAsString(new DateDto(ZonedDateTime.of(1988, 11, 17, 0, 0, 0, 0, ZoneId.of("Europe/Paris")))); + } +} diff --git a/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/JacksonRestClientTest.java b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/JacksonRestClientTest.java new file mode 100644 index 0000000000000..2592ce4a05d6f --- /dev/null +++ b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/JacksonRestClientTest.java @@ -0,0 +1,28 @@ +package io.quarkus.restclient.jackson.deployment; + +import static org.hamcrest.Matchers.is; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class JacksonRestClientTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withConfigurationResource("application.properties") + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(ZonedDateTimeObjectMapperCustomizer.class, DateDto.class, HelloResource.class, + RestInterface.class, + ClientResource.class)); + + @Test + public void testCustomDeserialization() { + RestAssured.get("/client/hello").then() + .body(is("OK")); + } +} diff --git a/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/RestInterface.java b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/RestInterface.java new file mode 100644 index 0000000000000..637a7b3424790 --- /dev/null +++ b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/RestInterface.java @@ -0,0 +1,19 @@ +package io.quarkus.restclient.jackson.deployment; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient +@Path("/hello") +@RegisterClientHeaders +public interface RestInterface { + + @GET + @Produces(MediaType.APPLICATION_JSON) + DateDto get(); +} diff --git a/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/ZonedDateTimeObjectMapperCustomizer.java b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/ZonedDateTimeObjectMapperCustomizer.java new file mode 100644 index 0000000000000..8c0ba48a63e7f --- /dev/null +++ b/extensions/rest-client-jackson/deployment/src/test/java/io/quarkus/restclient/jackson/deployment/ZonedDateTimeObjectMapperCustomizer.java @@ -0,0 +1,43 @@ +package io.quarkus.restclient.jackson.deployment; + +import java.io.IOException; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatterBuilder; + +import javax.inject.Singleton; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer; + +import io.quarkus.jackson.ObjectMapperCustomizer; + +@Singleton +public class ZonedDateTimeObjectMapperCustomizer implements ObjectMapperCustomizer { + + @Override + public void customize(ObjectMapper objectMapper) { + JavaTimeModule customDateModule = new JavaTimeModule(); + customDateModule.addSerializer(ZonedDateTime.class, new ZonedDateTimeSerializer( + new DateTimeFormatterBuilder().appendInstant(0).toFormatter().withZone(ZoneId.of("Z")))); + customDateModule.addDeserializer(ZonedDateTime.class, new ZonedDateTimeEuropeLondonDeserializer()); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .registerModule(customDateModule); + } + + public static class ZonedDateTimeEuropeLondonDeserializer extends JsonDeserializer { + + @Override + public ZonedDateTime deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + return ZonedDateTime.parse(p.getValueAsString()) + .withZoneSameInstant(ZoneId.of("Europe/London")); + } + } +} diff --git a/extensions/rest-client-jackson/deployment/src/test/resources/application.properties b/extensions/rest-client-jackson/deployment/src/test/resources/application.properties new file mode 100644 index 0000000000000..1d51622ea9c75 --- /dev/null +++ b/extensions/rest-client-jackson/deployment/src/test/resources/application.properties @@ -0,0 +1 @@ +io.quarkus.restclient.jackson.deployment.RestInterface/mp-rest/url=${test.url} \ No newline at end of file diff --git a/extensions/rest-client-jackson/pom.xml b/extensions/rest-client-jackson/pom.xml new file mode 100644 index 0000000000000..aa8a722224a18 --- /dev/null +++ b/extensions/rest-client-jackson/pom.xml @@ -0,0 +1,20 @@ + + + + quarkus-build-parent + io.quarkus + 999-SNAPSHOT + ../../build-parent/pom.xml + + 4.0.0 + + quarkus-rest-client-jackson-parent + Quarkus - REST Client - Jackson + pom + + deployment + runtime + + diff --git a/extensions/rest-client-jackson/runtime/pom.xml b/extensions/rest-client-jackson/runtime/pom.xml new file mode 100644 index 0000000000000..6345ed9f89ed9 --- /dev/null +++ b/extensions/rest-client-jackson/runtime/pom.xml @@ -0,0 +1,65 @@ + + + + quarkus-rest-client-jackson-parent + io.quarkus + 999-SNAPSHOT + ../ + + 4.0.0 + + quarkus-rest-client-jackson + Quarkus - REST Client - Jackson - Runtime + Enable Jackson serialization for the REST Client + + + io.quarkus + quarkus-rest-client + + + io.quarkus + quarkus-jackson + + + org.jboss.resteasy + resteasy-jackson2-provider + + + jakarta.xml.bind + jakarta.xml.bind-api + + + org.checkerframework + checker-qual + + + + + org.jboss.spec.javax.xml.bind + jboss-jaxb-api_2.3_spec + + + + + + + io.quarkus + quarkus-bootstrap-maven-plugin + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + diff --git a/extensions/rest-client-jackson/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/rest-client-jackson/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 0000000000000..4d66fad1169b8 --- /dev/null +++ b/extensions/rest-client-jackson/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,14 @@ +--- +name: "REST Client Jackson" +metadata: + keywords: + - "rest-client-jackson" + - "rest-client" + - "web-client" + - "microprofile-rest-client" + - "json" + - "jackson" + categories: + - "web" + - "serialization" + status: "stable" diff --git a/extensions/rest-client-jaxb/deployment/pom.xml b/extensions/rest-client-jaxb/deployment/pom.xml new file mode 100644 index 0000000000000..bb138d8671489 --- /dev/null +++ b/extensions/rest-client-jaxb/deployment/pom.xml @@ -0,0 +1,64 @@ + + + + quarkus-rest-client-jaxb-parent + io.quarkus + 999-SNAPSHOT + ../ + + 4.0.0 + + quarkus-rest-client-jaxb-deployment + Quarkus - REST Client - JAXB - Deployment + + + + io.quarkus + quarkus-rest-client-deployment + + + io.quarkus + quarkus-rest-client-jaxb + + + io.quarkus + quarkus-jaxb-deployment + + + + io.quarkus + quarkus-resteasy-deployment + test + + + io.quarkus + quarkus-junit5-internal + test + + + io.rest-assured + rest-assured + test + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/rest-client-jaxb/deployment/src/main/java/io/quarkus/restclient/jaxb/deployment/RestClientJaxbProcessor.java b/extensions/rest-client-jaxb/deployment/src/main/java/io/quarkus/restclient/jaxb/deployment/RestClientJaxbProcessor.java new file mode 100755 index 0000000000000..929ff4fdfd885 --- /dev/null +++ b/extensions/rest-client-jaxb/deployment/src/main/java/io/quarkus/restclient/jaxb/deployment/RestClientJaxbProcessor.java @@ -0,0 +1,13 @@ +package io.quarkus.restclient.jaxb.deployment; + +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.FeatureBuildItem; + +public class RestClientJaxbProcessor { + + @BuildStep + void build(BuildProducer feature) { + feature.produce(new FeatureBuildItem(FeatureBuildItem.REST_CLIENT_JAXB)); + } +} diff --git a/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/Book.java b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/Book.java new file mode 100644 index 0000000000000..ac32ad10ed93c --- /dev/null +++ b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/Book.java @@ -0,0 +1,24 @@ +package io.quarkus.restclient.jaxb.deployment; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Book { + + private String title; + + public Book() { + } + + public Book(String title) { + this.title = title; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/ClientResource.java b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/ClientResource.java new file mode 100644 index 0000000000000..02f20ddb1df7f --- /dev/null +++ b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/ClientResource.java @@ -0,0 +1,27 @@ +package io.quarkus.restclient.jaxb.deployment; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@Path("/client") +public class ClientResource { + + @Inject + @RestClient + RestInterface restInterface; + + @GET + @Path("/hello") + public String hello() { + Book book = restInterface.get(); + + if ("L'axe du loup".equals(book.getTitle())) { + return "OK"; + } + + return "INVALID"; + } +} diff --git a/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/HelloResource.java b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/HelloResource.java new file mode 100644 index 0000000000000..cd54bc7b65a66 --- /dev/null +++ b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/HelloResource.java @@ -0,0 +1,16 @@ +package io.quarkus.restclient.jaxb.deployment; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Produces(MediaType.APPLICATION_XML) +@Path("/hello") +public class HelloResource { + + @GET + public String hello() { + return "L'axe du loup"; + } +} diff --git a/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/JaxbRestClientTest.java b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/JaxbRestClientTest.java new file mode 100644 index 0000000000000..f665f95352afb --- /dev/null +++ b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/JaxbRestClientTest.java @@ -0,0 +1,29 @@ +package io.quarkus.restclient.jaxb.deployment; + +import static org.hamcrest.Matchers.is; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class JaxbRestClientTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withConfigurationResource("application.properties") + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(Book.class, + HelloResource.class, + RestInterface.class, + ClientResource.class)); + + @Test + public void testJaxb() { + RestAssured.get("/client/hello").then() + .body(is("OK")); + } +} diff --git a/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/RestInterface.java b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/RestInterface.java new file mode 100644 index 0000000000000..f985b39eebe5e --- /dev/null +++ b/extensions/rest-client-jaxb/deployment/src/test/java/io/quarkus/restclient/jaxb/deployment/RestInterface.java @@ -0,0 +1,19 @@ +package io.quarkus.restclient.jaxb.deployment; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient +@Path("/hello") +@RegisterClientHeaders +public interface RestInterface { + + @GET + @Produces(MediaType.APPLICATION_XML) + Book get(); +} diff --git a/extensions/rest-client-jaxb/deployment/src/test/resources/application.properties b/extensions/rest-client-jaxb/deployment/src/test/resources/application.properties new file mode 100644 index 0000000000000..99628eb948087 --- /dev/null +++ b/extensions/rest-client-jaxb/deployment/src/test/resources/application.properties @@ -0,0 +1 @@ +io.quarkus.restclient.jaxb.deployment.RestInterface/mp-rest/url=${test.url} \ No newline at end of file diff --git a/extensions/rest-client-jaxb/pom.xml b/extensions/rest-client-jaxb/pom.xml new file mode 100644 index 0000000000000..9f3f7210e808f --- /dev/null +++ b/extensions/rest-client-jaxb/pom.xml @@ -0,0 +1,20 @@ + + + + quarkus-build-parent + io.quarkus + 999-SNAPSHOT + ../../build-parent/pom.xml + + 4.0.0 + + quarkus-rest-client-jaxb-parent + Quarkus - REST Client - JAXB + pom + + deployment + runtime + + diff --git a/extensions/rest-client-jaxb/runtime/pom.xml b/extensions/rest-client-jaxb/runtime/pom.xml new file mode 100644 index 0000000000000..77345e8877a65 --- /dev/null +++ b/extensions/rest-client-jaxb/runtime/pom.xml @@ -0,0 +1,55 @@ + + + + quarkus-rest-client-jaxb-parent + io.quarkus + 999-SNAPSHOT + ../ + + 4.0.0 + + quarkus-rest-client-jaxb + Quarkus - REST Client - JAXB - Runtime + Enable XML serialization for the REST Client + + + io.quarkus + quarkus-rest-client + + + io.quarkus + quarkus-jaxb + + + org.jboss.resteasy + resteasy-jaxb-provider + + + org.jboss.spec.javax.xml.bind + jboss-jaxb-api_2.3_spec + + + + + + + io.quarkus + quarkus-bootstrap-maven-plugin + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + diff --git a/extensions/rest-client-jaxb/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/rest-client-jaxb/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 0000000000000..25c6fd88fe662 --- /dev/null +++ b/extensions/rest-client-jaxb/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,13 @@ +--- +name: "REST Client JAXB" +metadata: + keywords: + - "rest-client-jaxb" + - "rest-client" + - "web-client" + - "microprofile-rest-client" + - "jaxb" + categories: + - "web" + - "serialization" + status: "stable" diff --git a/extensions/rest-client-jsonb/deployment/pom.xml b/extensions/rest-client-jsonb/deployment/pom.xml new file mode 100644 index 0000000000000..0505299df2dba --- /dev/null +++ b/extensions/rest-client-jsonb/deployment/pom.xml @@ -0,0 +1,64 @@ + + + + quarkus-rest-client-jsonb-parent + io.quarkus + 999-SNAPSHOT + ../ + + 4.0.0 + + quarkus-rest-client-jsonb-deployment + Quarkus - REST Client - JSON-B - Deployment + + + + io.quarkus + quarkus-rest-client-deployment + + + io.quarkus + quarkus-rest-client-jsonb + + + io.quarkus + quarkus-jsonb-deployment + + + + io.quarkus + quarkus-resteasy-deployment + test + + + io.quarkus + quarkus-junit5-internal + test + + + io.rest-assured + rest-assured + test + + + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + + diff --git a/extensions/rest-client-jsonb/deployment/src/main/java/io/quarkus/restclient/jsonb/deployment/RestClientJsonbProcessor.java b/extensions/rest-client-jsonb/deployment/src/main/java/io/quarkus/restclient/jsonb/deployment/RestClientJsonbProcessor.java new file mode 100755 index 0000000000000..150147e8883e3 --- /dev/null +++ b/extensions/rest-client-jsonb/deployment/src/main/java/io/quarkus/restclient/jsonb/deployment/RestClientJsonbProcessor.java @@ -0,0 +1,18 @@ +package io.quarkus.restclient.jsonb.deployment; + +import io.quarkus.deployment.Capabilities; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.CapabilityBuildItem; +import io.quarkus.deployment.builditem.FeatureBuildItem; + +public class RestClientJsonbProcessor { + + @BuildStep + void build(BuildProducer feature, + BuildProducer capability) { + feature.produce(new FeatureBuildItem(FeatureBuildItem.REST_CLIENT_JSONB)); + + capability.produce(new CapabilityBuildItem(Capabilities.REST_JSONB)); + } +} diff --git a/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/ClientResource.java b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/ClientResource.java new file mode 100644 index 0000000000000..1158b89e0c5f6 --- /dev/null +++ b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/ClientResource.java @@ -0,0 +1,33 @@ +package io.quarkus.restclient.jsonb.deployment; + +import java.time.Month; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@Path("/client") +public class ClientResource { + + @Inject + @RestClient + RestInterface restInterface; + + @GET + @Path("/hello") + public String hello() { + DateDto dateDto = restInterface.get(); + ZonedDateTime zonedDateTime = dateDto.getDate(); + + if (zonedDateTime.getMonth().equals(Month.NOVEMBER) + && zonedDateTime.getZone().equals(ZoneId.of("Europe/Paris"))) { + return "OK"; + } + + return "INVALID"; + } +} diff --git a/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/DateDto.java b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/DateDto.java new file mode 100644 index 0000000000000..52d8c639ced52 --- /dev/null +++ b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/DateDto.java @@ -0,0 +1,23 @@ +package io.quarkus.restclient.jsonb.deployment; + +import java.time.ZonedDateTime; + +public class DateDto { + + private ZonedDateTime date; + + public DateDto() { + } + + public DateDto(ZonedDateTime date) { + this.date = date; + } + + public void setDate(ZonedDateTime date) { + this.date = date; + } + + public ZonedDateTime getDate() { + return date; + } +} diff --git a/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/HelloResource.java b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/HelloResource.java new file mode 100644 index 0000000000000..6149f3a87a0c8 --- /dev/null +++ b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/HelloResource.java @@ -0,0 +1,24 @@ +package io.quarkus.restclient.jsonb.deployment; + +import java.time.ZonedDateTime; + +import javax.inject.Inject; +import javax.json.bind.Jsonb; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Produces(MediaType.APPLICATION_JSON) +@Path("/hello") +public class HelloResource { + + @Inject + Jsonb jsonb; + + @GET + public String hello() { + // we don't care about the value here as we will use a custom deserializer that returns a fixed value + return jsonb.toJson(new DateDto(ZonedDateTime.now())); + } +} diff --git a/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/JsonbRestClientTest.java b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/JsonbRestClientTest.java new file mode 100644 index 0000000000000..2317d1bcd331f --- /dev/null +++ b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/JsonbRestClientTest.java @@ -0,0 +1,28 @@ +package io.quarkus.restclient.jsonb.deployment; + +import static org.hamcrest.Matchers.is; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; + +public class JsonbRestClientTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withConfigurationResource("application.properties") + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(ZonedDateTimeJsonbConfigCustomizer.class, DateDto.class, HelloResource.class, + RestInterface.class, + ClientResource.class)); + + @Test + public void testCustomDeserialization() { + RestAssured.get("/client/hello").then() + .body(is("OK")); + } +} diff --git a/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/RestInterface.java b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/RestInterface.java new file mode 100644 index 0000000000000..6588dc1ab3f2d --- /dev/null +++ b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/RestInterface.java @@ -0,0 +1,19 @@ +package io.quarkus.restclient.jsonb.deployment; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient +@Path("/hello") +@RegisterClientHeaders +public interface RestInterface { + + @GET + @Produces(MediaType.APPLICATION_JSON) + DateDto get(); +} diff --git a/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/ZonedDateTimeJsonbConfigCustomizer.java b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/ZonedDateTimeJsonbConfigCustomizer.java new file mode 100644 index 0000000000000..12bcd9c99ec52 --- /dev/null +++ b/extensions/rest-client-jsonb/deployment/src/test/java/io/quarkus/restclient/jsonb/deployment/ZonedDateTimeJsonbConfigCustomizer.java @@ -0,0 +1,30 @@ +package io.quarkus.restclient.jsonb.deployment; + +import java.lang.reflect.Type; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import javax.inject.Singleton; +import javax.json.bind.JsonbConfig; +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.stream.JsonParser; + +import io.quarkus.jsonb.JsonbConfigCustomizer; + +@Singleton +public class ZonedDateTimeJsonbConfigCustomizer implements JsonbConfigCustomizer { + + @Override + public void customize(JsonbConfig jsonbConfig) { + jsonbConfig.withDeserializers(new ZonedDateTimeWeirdDeserializer()); + } + + public static class ZonedDateTimeWeirdDeserializer implements JsonbDeserializer { + + @Override + public ZonedDateTime deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + return ZonedDateTime.of(1988, 11, 17, 0, 0, 0, 0, ZoneId.of("Europe/Paris")); + } + } +} diff --git a/extensions/rest-client-jsonb/deployment/src/test/resources/application.properties b/extensions/rest-client-jsonb/deployment/src/test/resources/application.properties new file mode 100644 index 0000000000000..4bff6c7629f29 --- /dev/null +++ b/extensions/rest-client-jsonb/deployment/src/test/resources/application.properties @@ -0,0 +1 @@ +io.quarkus.restclient.jsonb.deployment.RestInterface/mp-rest/url=${test.url} \ No newline at end of file diff --git a/extensions/rest-client-jsonb/pom.xml b/extensions/rest-client-jsonb/pom.xml new file mode 100644 index 0000000000000..db67cf68d776b --- /dev/null +++ b/extensions/rest-client-jsonb/pom.xml @@ -0,0 +1,20 @@ + + + + quarkus-build-parent + io.quarkus + 999-SNAPSHOT + ../../build-parent/pom.xml + + 4.0.0 + + quarkus-rest-client-jsonb-parent + Quarkus - REST Client - JSON-B + pom + + deployment + runtime + + diff --git a/extensions/rest-client-jsonb/runtime/pom.xml b/extensions/rest-client-jsonb/runtime/pom.xml new file mode 100644 index 0000000000000..f25528fdba94f --- /dev/null +++ b/extensions/rest-client-jsonb/runtime/pom.xml @@ -0,0 +1,60 @@ + + + + quarkus-rest-client-jsonb-parent + io.quarkus + 999-SNAPSHOT + ../ + + 4.0.0 + + quarkus-rest-client-jsonb + Quarkus - REST Client - JSON-B - Runtime + Enable JSON-B serialization for the REST client + + + + io.quarkus + quarkus-rest-client + + + io.quarkus + quarkus-jsonb + + + org.jboss.resteasy + resteasy-json-binding-provider + + + org.jboss.resteasy + resteasy-json-p-provider + + + commons-io + commons-io + + + + + + + io.quarkus + quarkus-bootstrap-maven-plugin + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + diff --git a/extensions/rest-client-jsonb/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/rest-client-jsonb/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 0000000000000..b319d5b3bbaac --- /dev/null +++ b/extensions/rest-client-jsonb/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,14 @@ +--- +name: "REST Client JSON-B" +metadata: + keywords: + - "rest-client-jsonb" + - "rest-client" + - "web-client" + - "microprofile-rest-client" + - "json" + - "jsonb" + categories: + - "web" + - "serialization" + status: "stable" diff --git a/extensions/rest-client/deployment/pom.xml b/extensions/rest-client/deployment/pom.xml index 899a0a6b61835..87422b675ea5e 100644 --- a/extensions/rest-client/deployment/pom.xml +++ b/extensions/rest-client/deployment/pom.xml @@ -11,7 +11,7 @@ 4.0.0 quarkus-rest-client-deployment - Quarkus - REST client - Deployment + Quarkus - REST Client - Deployment diff --git a/extensions/rest-client/pom.xml b/extensions/rest-client/pom.xml index 05ff19bb5bf35..6753563041001 100644 --- a/extensions/rest-client/pom.xml +++ b/extensions/rest-client/pom.xml @@ -11,7 +11,7 @@ 4.0.0 quarkus-rest-client-parent - Quarkus - REST client + Quarkus - REST Client pom deployment diff --git a/extensions/rest-client/runtime/pom.xml b/extensions/rest-client/runtime/pom.xml index 123991ff71fa9..0eb84cb596d9a 100644 --- a/extensions/rest-client/runtime/pom.xml +++ b/extensions/rest-client/runtime/pom.xml @@ -11,7 +11,7 @@ 4.0.0 quarkus-rest-client - Quarkus - REST client - Runtime + Quarkus - REST Client - Runtime Call REST services diff --git a/extensions/resteasy-common/deployment/src/main/java/io/quarkus/resteasy/common/deployment/ResteasyCommonProcessor.java b/extensions/resteasy-common/deployment/src/main/java/io/quarkus/resteasy/common/deployment/ResteasyCommonProcessor.java index 4e826751ac24f..7b91c994c2699 100644 --- a/extensions/resteasy-common/deployment/src/main/java/io/quarkus/resteasy/common/deployment/ResteasyCommonProcessor.java +++ b/extensions/resteasy-common/deployment/src/main/java/io/quarkus/resteasy/common/deployment/ResteasyCommonProcessor.java @@ -38,8 +38,11 @@ import org.jboss.resteasy.plugins.providers.sse.SseConstants; import org.jboss.resteasy.spi.InjectorFactory; +import io.quarkus.arc.deployment.AdditionalBeanBuildItem; import io.quarkus.arc.deployment.BeanArchiveIndexBuildItem; import io.quarkus.arc.deployment.BeanContainerBuildItem; +import io.quarkus.arc.deployment.UnremovableBeanBuildItem; +import io.quarkus.arc.processor.DotNames; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; @@ -57,6 +60,7 @@ import io.quarkus.runtime.configuration.MemorySize; public class ResteasyCommonProcessor { + private static final Logger LOGGER = Logger.getLogger(ResteasyCommonProcessor.class.getName()); private static final ProviderDiscoverer[] PROVIDER_DISCOVERERS = { @@ -69,6 +73,13 @@ public class ResteasyCommonProcessor { new ProviderDiscoverer(ResteasyDotNames.PUT, true, false) }; + private static final DotName QUARKUS_OBJECT_MAPPER_CONTEXT_RESOLVER = DotName + .createSimple("io.quarkus.resteasy.common.runtime.jackson.QuarkusObjectMapperContextResolver"); + private static final DotName OBJECT_MAPPER = DotName.createSimple("com.fasterxml.jackson.databind.ObjectMapper"); + private static final DotName QUARKUS_JSONB_CONTEXT_RESOLVER = DotName + .createSimple("io.quarkus.resteasy.common.runtime.jsonb.QuarkusJsonbContextResolver"); + private static final DotName JSONB = DotName.createSimple("javax.json.bind.Jsonb"); + private ResteasyCommonConfig resteasyCommonConfig; @ConfigRoot(name = "resteasy") @@ -191,6 +202,62 @@ JaxrsProvidersToRegisterBuildItem setupProviders(BuildProducer jaxrsProvider, + BuildProducer additionalBean, + BuildProducer unremovable) { + + if (capabilities.isCapabilityPresent(Capabilities.REST_JACKSON)) { + registerJsonContextResolver(OBJECT_MAPPER, QUARKUS_OBJECT_MAPPER_CONTEXT_RESOLVER, combinedIndexBuildItem, + jaxrsProvider, additionalBean, unremovable); + } + + if (capabilities.isCapabilityPresent(Capabilities.REST_JSONB)) { + registerJsonContextResolver(JSONB, QUARKUS_JSONB_CONTEXT_RESOLVER, combinedIndexBuildItem, jaxrsProvider, + additionalBean, unremovable); + } + } + + private void registerJsonContextResolver( + DotName jsonImplementation, + DotName jsonContextResolver, + CombinedIndexBuildItem combinedIndexBuildItem, + BuildProducer jaxrsProvider, + BuildProducer additionalBean, + BuildProducer unremovable) { + + IndexView index = combinedIndexBuildItem.getIndex(); + + jaxrsProvider.produce(new ResteasyJaxrsProviderBuildItem(jsonContextResolver.toString())); + + // this needs to be registered manually since the runtime module is not indexed by Jandex + additionalBean.produce(AdditionalBeanBuildItem.unremovableOf(jsonContextResolver.toString())); + Set userSuppliedProducers = getUserSuppliedJsonProducerBeans(index, jsonImplementation); + if (!userSuppliedProducers.isEmpty()) { + unremovable.produce( + new UnremovableBeanBuildItem(new UnremovableBeanBuildItem.BeanClassNamesExclusion(userSuppliedProducers))); + } + } + + /* + * We need to find all the user supplied producers and mark them as unremovable since there are no actual injection points + * for ObjectMapper/Jsonb. + */ + private Set getUserSuppliedJsonProducerBeans(IndexView index, DotName jsonImplementation) { + Set result = new HashSet<>(); + for (AnnotationInstance annotation : index.getAnnotations(DotNames.PRODUCES)) { + if (annotation.target().kind() != AnnotationTarget.Kind.METHOD) { + continue; + } + if (jsonImplementation.equals(annotation.target().asMethod().returnType().name())) { + result.add(annotation.target().asMethod().declaringClass().name().toString()); + } + } + return result; + } + private void checkProperConfigAccessInProvider(AnnotationInstance instance) { List configPropertyInstances = instance.target().asClass().annotations() .get(ResteasyDotNames.CONFIG_PROPERTY); diff --git a/extensions/resteasy-common/runtime/pom.xml b/extensions/resteasy-common/runtime/pom.xml index 35ae2dcf4108f..f867901d5f320 100644 --- a/extensions/resteasy-common/runtime/pom.xml +++ b/extensions/resteasy-common/runtime/pom.xml @@ -12,7 +12,7 @@ quarkus-resteasy-common Quarkus - RESTEasy - Common - Runtime - REST framework implementing JAX-RS and more + Components common to the RESTEasy server and the REST Client org.graalvm.nativeimage @@ -46,6 +46,16 @@ com.sun.activation jakarta.activation + + com.fasterxml.jackson.core + jackson-databind + true + + + jakarta.json.bind + jakarta.json.bind-api + true + diff --git a/extensions/resteasy-jackson/runtime/src/main/java/io/quarkus/resteasy/jackson/runtime/QuarkusObjectMapperContextResolver.java b/extensions/resteasy-common/runtime/src/main/java/io/quarkus/resteasy/common/runtime/jackson/QuarkusObjectMapperContextResolver.java similarity index 92% rename from extensions/resteasy-jackson/runtime/src/main/java/io/quarkus/resteasy/jackson/runtime/QuarkusObjectMapperContextResolver.java rename to extensions/resteasy-common/runtime/src/main/java/io/quarkus/resteasy/common/runtime/jackson/QuarkusObjectMapperContextResolver.java index 45e5c983b5db4..338831749d370 100644 --- a/extensions/resteasy-jackson/runtime/src/main/java/io/quarkus/resteasy/jackson/runtime/QuarkusObjectMapperContextResolver.java +++ b/extensions/resteasy-common/runtime/src/main/java/io/quarkus/resteasy/common/runtime/jackson/QuarkusObjectMapperContextResolver.java @@ -1,4 +1,4 @@ -package io.quarkus.resteasy.jackson.runtime; +package io.quarkus.resteasy.common.runtime.jackson; import javax.annotation.Priority; import javax.enterprise.context.ApplicationScoped; diff --git a/extensions/resteasy-jsonb/runtime/src/main/java/io/quarkus/resteasy/jsonb/runtime/QuarkusJsonbContextResolver.java b/extensions/resteasy-common/runtime/src/main/java/io/quarkus/resteasy/common/runtime/jsonb/QuarkusJsonbContextResolver.java similarity index 92% rename from extensions/resteasy-jsonb/runtime/src/main/java/io/quarkus/resteasy/jsonb/runtime/QuarkusJsonbContextResolver.java rename to extensions/resteasy-common/runtime/src/main/java/io/quarkus/resteasy/common/runtime/jsonb/QuarkusJsonbContextResolver.java index a392b321934e0..16b9412db5853 100644 --- a/extensions/resteasy-jsonb/runtime/src/main/java/io/quarkus/resteasy/jsonb/runtime/QuarkusJsonbContextResolver.java +++ b/extensions/resteasy-common/runtime/src/main/java/io/quarkus/resteasy/common/runtime/jsonb/QuarkusJsonbContextResolver.java @@ -1,4 +1,4 @@ -package io.quarkus.resteasy.jsonb.runtime; +package io.quarkus.resteasy.common.runtime.jsonb; import javax.annotation.Priority; import javax.enterprise.context.ApplicationScoped; diff --git a/extensions/resteasy-jackson/deployment/src/main/java/io/quarkus/resteasy/jackson/deployment/ResteasyJacksonProcessor.java b/extensions/resteasy-jackson/deployment/src/main/java/io/quarkus/resteasy/jackson/deployment/ResteasyJacksonProcessor.java index 0ed222343af8f..378a310b9861a 100644 --- a/extensions/resteasy-jackson/deployment/src/main/java/io/quarkus/resteasy/jackson/deployment/ResteasyJacksonProcessor.java +++ b/extensions/resteasy-jackson/deployment/src/main/java/io/quarkus/resteasy/jackson/deployment/ResteasyJacksonProcessor.java @@ -1,68 +1,21 @@ package io.quarkus.resteasy.jackson.deployment; -import java.util.HashSet; -import java.util.Set; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.DotName; -import org.jboss.jandex.IndexView; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import io.quarkus.arc.deployment.AdditionalBeanBuildItem; -import io.quarkus.arc.deployment.UnremovableBeanBuildItem; -import io.quarkus.arc.processor.DotNames; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; -import io.quarkus.deployment.builditem.CombinedIndexBuildItem; +import io.quarkus.deployment.builditem.CapabilityBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; -import io.quarkus.resteasy.common.spi.ResteasyJaxrsProviderBuildItem; -import io.quarkus.resteasy.jackson.runtime.QuarkusObjectMapperContextResolver; public class ResteasyJacksonProcessor { - private static final DotName OBJECT_MAPPER = DotName.createSimple(ObjectMapper.class.getName()); - - @BuildStep(providesCapabilities = { Capabilities.RESTEASY_JSON_EXTENSION }) - void build(BuildProducer feature) { + @BuildStep + void feature(BuildProducer feature) { feature.produce(new FeatureBuildItem(FeatureBuildItem.RESTEASY_JACKSON)); } @BuildStep - void register(CombinedIndexBuildItem combinedIndexBuildItem, - BuildProducer jaxrsProvider, - BuildProducer additionalBean, - BuildProducer unremovable) { - - IndexView index = combinedIndexBuildItem.getIndex(); - - jaxrsProvider.produce(new ResteasyJaxrsProviderBuildItem(QuarkusObjectMapperContextResolver.class.getName())); - - // this needs to be registered manually since the runtime module is not indexed by Jandex - additionalBean.produce(AdditionalBeanBuildItem.unremovableOf(QuarkusObjectMapperContextResolver.class)); - Set userSuppliedProducers = getUserSuppliedJacksonProducerBeans(index); - if (!userSuppliedProducers.isEmpty()) { - unremovable.produce( - new UnremovableBeanBuildItem(new UnremovableBeanBuildItem.BeanClassNamesExclusion(userSuppliedProducers))); - } - } - - /* - * We need to find all the user supplied producers and mark them as unremovable since there are no actual injection points - * for the ObjectMapper - */ - private Set getUserSuppliedJacksonProducerBeans(IndexView index) { - Set result = new HashSet<>(); - for (AnnotationInstance annotation : index.getAnnotations(DotNames.PRODUCES)) { - if (annotation.target().kind() != AnnotationTarget.Kind.METHOD) { - continue; - } - if (OBJECT_MAPPER.equals(annotation.target().asMethod().returnType().name())) { - result.add(annotation.target().asMethod().declaringClass().name().toString()); - } - } - return result; + void capabilities(BuildProducer capability) { + capability.produce(new CapabilityBuildItem(Capabilities.RESTEASY_JSON_EXTENSION)); + capability.produce(new CapabilityBuildItem(Capabilities.REST_JACKSON)); } } diff --git a/extensions/resteasy-jsonb/deployment/src/main/java/io/quarkus/resteasy/jsonb/deployment/ResteasyJsonbProcessor.java b/extensions/resteasy-jsonb/deployment/src/main/java/io/quarkus/resteasy/jsonb/deployment/ResteasyJsonbProcessor.java index 8d9467f221de7..0ac9dbbe76990 100755 --- a/extensions/resteasy-jsonb/deployment/src/main/java/io/quarkus/resteasy/jsonb/deployment/ResteasyJsonbProcessor.java +++ b/extensions/resteasy-jsonb/deployment/src/main/java/io/quarkus/resteasy/jsonb/deployment/ResteasyJsonbProcessor.java @@ -1,74 +1,21 @@ package io.quarkus.resteasy.jsonb.deployment; -import java.util.HashSet; -import java.util.Set; - -import javax.json.bind.Jsonb; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.DotName; -import org.jboss.jandex.IndexView; - -import io.quarkus.arc.deployment.AdditionalBeanBuildItem; -import io.quarkus.arc.deployment.UnremovableBeanBuildItem; -import io.quarkus.arc.processor.DotNames; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.CapabilityBuildItem; -import io.quarkus.deployment.builditem.CombinedIndexBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; -import io.quarkus.resteasy.common.spi.ResteasyJaxrsProviderBuildItem; -import io.quarkus.resteasy.jsonb.runtime.QuarkusJsonbContextResolver; public class ResteasyJsonbProcessor { - private static final DotName JSONB = DotName.createSimple(Jsonb.class.getName()); - - @BuildStep - CapabilityBuildItem capability() { - return new CapabilityBuildItem(Capabilities.RESTEASY_JSON_EXTENSION); - } - @BuildStep - void build(BuildProducer feature) { + void feature(BuildProducer feature) { feature.produce(new FeatureBuildItem(FeatureBuildItem.RESTEASY_JSONB)); } @BuildStep - void register(CombinedIndexBuildItem combinedIndexBuildItem, - BuildProducer jaxrsProvider, - BuildProducer additionalBean, - BuildProducer unremovable) { - - IndexView index = combinedIndexBuildItem.getIndex(); - - jaxrsProvider.produce(new ResteasyJaxrsProviderBuildItem(QuarkusJsonbContextResolver.class.getName())); - - // this needs to be registered manually since the runtime module is not indexed by Jandex - additionalBean.produce(AdditionalBeanBuildItem.unremovableOf(QuarkusJsonbContextResolver.class)); - Set userSuppliedProducers = getUserSuppliedJsonbProducerBeans(index); - if (!userSuppliedProducers.isEmpty()) { - unremovable.produce( - new UnremovableBeanBuildItem(new UnremovableBeanBuildItem.BeanClassNamesExclusion(userSuppliedProducers))); - } - } - - /* - * We need to find all the user supplied producers and mark them as unremovable since there might be no injection points - * for the Jsonb - */ - private Set getUserSuppliedJsonbProducerBeans(IndexView index) { - Set result = new HashSet<>(); - for (AnnotationInstance annotation : index.getAnnotations(DotNames.PRODUCES)) { - if (annotation.target().kind() != AnnotationTarget.Kind.METHOD) { - continue; - } - if (JSONB.equals(annotation.target().asMethod().returnType().name())) { - result.add(annotation.target().asMethod().declaringClass().name().toString()); - } - } - return result; + void capabilities(BuildProducer capability) { + capability.produce(new CapabilityBuildItem(Capabilities.RESTEASY_JSON_EXTENSION)); + capability.produce(new CapabilityBuildItem(Capabilities.REST_JSONB)); } } diff --git a/integration-tests/resteasy-jackson/src/test/java/io/quarkus/it/resteasy/jackson/GeneratedClassesTest.java b/integration-tests/resteasy-jackson/src/test/java/io/quarkus/it/resteasy/jackson/GeneratedClassesTest.java index 87ea6501174bd..f5abd253a65cf 100644 --- a/integration-tests/resteasy-jackson/src/test/java/io/quarkus/it/resteasy/jackson/GeneratedClassesTest.java +++ b/integration-tests/resteasy-jackson/src/test/java/io/quarkus/it/resteasy/jackson/GeneratedClassesTest.java @@ -16,9 +16,9 @@ void testGeneratedContextResolver() { private Object generatedContextResolver() { try { - Class jsonbResolverClass = Class - .forName("io.quarkus.resteasy.jackson.runtime.QuarkusObjectMapperContextResolver"); - return jsonbResolverClass.newInstance(); + Class objectMapperResolverClass = Class + .forName("io.quarkus.resteasy.common.runtime.jackson.QuarkusObjectMapperContextResolver"); + return objectMapperResolverClass.newInstance(); } catch (Exception e) { throw new RuntimeException(e); }