From becda000946494c427b9600c73b836425932b118 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Tue, 20 Sep 2022 16:10:16 +0300 Subject: [PATCH] Make RESTEasy Reactive work with Optional temporal types Fixes: #28089 --- .../common/processor/EndpointIndexer.java | 13 ++++--- .../processor/ServerEndpointIndexer.java | 36 ++++++++++--------- .../test/simple/LocalDateTimeParamTest.java | 16 +++++++++ 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java index 9724c6a250fd3..9f9fdc15a1eda 100644 --- a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java +++ b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java @@ -146,7 +146,7 @@ public abstract class EndpointIndexer SUPPORT_TEMPORAL_PARAMS = Set.of(INSTANT, LOCAL_DATE, LOCAL_TIME, LOCAL_DATE_TIME, + protected static final Set SUPPORT_TEMPORAL_PARAMS = Set.of(INSTANT, LOCAL_DATE, LOCAL_TIME, LOCAL_DATE_TIME, OFFSET_TIME, OFFSET_DATE_TIME, ZONED_DATE_TIME); @@ -1281,8 +1281,8 @@ && isContextType(paramType.asClassType())) { currentClassInfo, actualEndpointInfo, index); } - handleOptionalParam(existingConverters, errorLocation, hasRuntimeConverters, builder, elementType, - genericElementType); + handleOptionalParam(existingConverters, anns, errorLocation, hasRuntimeConverters, builder, elementType, + genericElementType, currentMethodInfo); } builder.setOptional(true); } else if (convertible) { @@ -1380,8 +1380,11 @@ protected void handleSortedSetParam(Map existingConverters, Stri boolean hasRuntimeConverters, PARAM builder, String elementType) { } - protected void handleOptionalParam(Map existingConverters, String errorLocation, - boolean hasRuntimeConverters, PARAM builder, String elementType, String genericElementType) { + protected void handleOptionalParam(Map existingConverters, + Map parameterAnnotations, + String errorLocation, + boolean hasRuntimeConverters, PARAM builder, String elementType, String genericElementType, + MethodInfo currentMethodInfo) { } protected void handleSetParam(Map existingConverters, String errorLocation, boolean hasRuntimeConverters, diff --git a/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java b/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java index 71f97a2232fad..c0db121284283 100644 --- a/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java +++ b/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java @@ -333,8 +333,11 @@ protected void handleSortedSetParam(Map existingConverters, Stri builder.setConverter(new SortedSetConverter.SortedSetSupplier(converter)); } - protected void handleOptionalParam(Map existingConverters, String errorLocation, - boolean hasRuntimeConverters, ServerIndexedParameter builder, String elementType, String genericElementType) { + protected void handleOptionalParam(Map existingConverters, + Map parameterAnnotations, + String errorLocation, + boolean hasRuntimeConverters, ServerIndexedParameter builder, String elementType, String genericElementType, + MethodInfo currentMethodInfo) { ParameterConverterSupplier converter = null; if (genericElementType != null) { @@ -350,6 +353,9 @@ protected void handleOptionalParam(Map existingConverters, Strin converter = new SortedSetConverter.SortedSetSupplier(genericTypeConverter); builder.setSingle(false); } + } else if (SUPPORT_TEMPORAL_PARAMS.contains(DotName.createSimple(elementType))) { + converter = determineTemporalConverter(DotName.createSimple(elementType), parameterAnnotations, + currentMethodInfo); } if (converter == null) { @@ -393,6 +399,11 @@ protected String handleTrailingSlash(String path) { protected void handleTemporalParam(ServerIndexedParameter builder, DotName paramType, Map parameterAnnotations, MethodInfo currentMethodInfo) { + builder.setConverter(determineTemporalConverter(paramType, parameterAnnotations, currentMethodInfo)); + } + + private ParameterConverterSupplier determineTemporalConverter(DotName paramType, + Map parameterAnnotations, MethodInfo currentMethodInfo) { String format = null; String dateTimeFormatterProviderClassName = null; @@ -416,8 +427,7 @@ protected void handleTemporalParam(ServerIndexedParameter builder, DotName param "'java.time.Instant' types must not be annotated with '@DateFormat'", currentMethodInfo)); } - builder.setConverter(new InstantParamConverter.Supplier()); - return; + return new InstantParamConverter.Supplier(); } if ((format != null) && (dateTimeFormatterProviderClassName != null)) { @@ -430,23 +440,17 @@ protected void handleTemporalParam(ServerIndexedParameter builder, DotName param } if (LOCAL_DATE.equals(paramType)) { - builder.setConverter(new LocalDateParamConverter.Supplier(format, dateTimeFormatterProviderClassName)); - return; + return new LocalDateParamConverter.Supplier(format, dateTimeFormatterProviderClassName); } else if (LOCAL_DATE_TIME.equals(paramType)) { - builder.setConverter(new LocalDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName)); - return; + return new LocalDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName); } else if (LOCAL_TIME.equals(paramType)) { - builder.setConverter(new LocalTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName)); - return; + return new LocalTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName); } else if (OFFSET_DATE_TIME.equals(paramType)) { - builder.setConverter(new OffsetDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName)); - return; + return new OffsetDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName); } else if (OFFSET_TIME.equals(paramType)) { - builder.setConverter(new OffsetTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName)); - return; + return new OffsetTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName); } else if (ZONED_DATE_TIME.equals(paramType)) { - builder.setConverter(new ZonedDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName)); - return; + return new ZonedDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName); } throw new RuntimeException( diff --git a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/simple/LocalDateTimeParamTest.java b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/simple/LocalDateTimeParamTest.java index 2159bb2f31950..f9bbef0af9bf3 100644 --- a/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/simple/LocalDateTimeParamTest.java +++ b/independent-projects/resteasy-reactive/server/vertx/src/test/java/org/jboss/resteasy/reactive/server/vertx/test/simple/LocalDateTimeParamTest.java @@ -3,6 +3,7 @@ import io.restassured.RestAssured; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.Optional; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -30,6 +31,15 @@ public void localDateTimeAsQueryParam() { .then().statusCode(200).body(Matchers.equalTo("hello#1984")); } + @Test + public void localDateTimeAsOptionalQueryParam() { + RestAssured.get("/hello/optional?date=1984-08-08T01:02:03") + .then().statusCode(200).body(Matchers.equalTo("hello#1984")); + + RestAssured.get("/hello/optional") + .then().statusCode(200).body(Matchers.equalTo("hello#2022")); + } + @Test public void localDateTimeAsPathParam() { RestAssured.get("/hello/1995-09-21 01:02:03") @@ -50,6 +60,12 @@ public String helloQuery(@RestQuery LocalDateTime date) { return "hello#" + date.getYear(); } + @Path("optional") + @GET + public String helloOptionalQuery(@RestQuery Optional date) { + return "hello#" + date.orElse(LocalDateTime.of(2022, 1, 1, 0, 0)).getYear(); + } + @GET @Path("{date}") public String helloPath(@RestPath @DateFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime date) {