Skip to content

Commit 2d68547

Browse files
committed
Add support for java.time.YearMonth as JAX-RS parameter
Blatant copy of geoand's PR #34324, but adding YearMonth.
1 parent f87ad4c commit 2d68547

File tree

5 files changed

+170
-1
lines changed

5 files changed

+170
-1
lines changed

independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.UNI;
8181
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.URI_INFO;
8282
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.YEAR;
83+
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.YEAR_MONTH;
8384
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.ZONED_DATE_TIME;
8485

8586
import java.lang.reflect.Modifier;
@@ -157,7 +158,7 @@ public abstract class EndpointIndexer<T extends EndpointIndexer<T, PARAM, METHOD
157158
RESOURCE_INFO);
158159

159160
protected static final Set<DotName> SUPPORT_TEMPORAL_PARAMS = Set.of(INSTANT, LOCAL_DATE, LOCAL_TIME, LOCAL_DATE_TIME,
160-
OFFSET_TIME, OFFSET_DATE_TIME, ZONED_DATE_TIME, YEAR);
161+
OFFSET_TIME, OFFSET_DATE_TIME, ZONED_DATE_TIME, YEAR, YEAR_MONTH);
161162

162163
protected static final Logger log = Logger.getLogger(EndpointIndexer.class);
163164
protected static final String[] EMPTY_STRING_ARRAY = new String[] {};

independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/ResteasyReactiveDotNames.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.time.OffsetDateTime;
1313
import java.time.OffsetTime;
1414
import java.time.Year;
15+
import java.time.YearMonth;
1516
import java.time.ZonedDateTime;
1617
import java.util.Arrays;
1718
import java.util.Collection;
@@ -203,6 +204,7 @@ public final class ResteasyReactiveDotNames {
203204
public static final DotName OFFSET_TIME = DotName.createSimple(OffsetTime.class.getName());
204205
public static final DotName ZONED_DATE_TIME = DotName.createSimple(ZonedDateTime.class.getName());
205206
public static final DotName YEAR = DotName.createSimple(Year.class.getName());
207+
public static final DotName YEAR_MONTH = DotName.createSimple(YearMonth.class.getName());
206208

207209
public static final DotName UNI = DotName.createSimple(Uni.class.getName());
208210
public static final DotName MULTI = DotName.createSimple(Multi.class.getName());

independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.SET;
2222
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.SORTED_SET;
2323
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.YEAR;
24+
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.YEAR_MONTH;
2425
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.ZONED_DATE_TIME;
2526

2627
import java.io.File;
@@ -83,6 +84,7 @@
8384
import org.jboss.resteasy.reactive.server.core.parameters.converters.RuntimeResolvedConverter;
8485
import org.jboss.resteasy.reactive.server.core.parameters.converters.SetConverter;
8586
import org.jboss.resteasy.reactive.server.core.parameters.converters.SortedSetConverter;
87+
import org.jboss.resteasy.reactive.server.core.parameters.converters.YearMonthParamConverter;
8688
import org.jboss.resteasy.reactive.server.core.parameters.converters.YearParamConverter;
8789
import org.jboss.resteasy.reactive.server.core.parameters.converters.ZonedDateTimeParamConverter;
8890
import org.jboss.resteasy.reactive.server.mapping.URITemplate;
@@ -623,6 +625,8 @@ private ParameterConverterSupplier determineTemporalConverter(DotName paramType,
623625
return new ZonedDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName);
624626
} else if (YEAR.equals(paramType)) {
625627
return new YearParamConverter.Supplier(format, dateTimeFormatterProviderClassName);
628+
} else if (YEAR_MONTH.equals(paramType)) {
629+
return new YearMonthParamConverter.Supplier(format, dateTimeFormatterProviderClassName);
626630
}
627631

628632
throw new RuntimeException(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package org.jboss.resteasy.reactive.server.core.parameters.converters;
2+
3+
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
4+
import static java.time.temporal.ChronoField.YEAR;
5+
6+
import java.time.YearMonth;
7+
import java.time.format.DateTimeFormatter;
8+
import java.time.format.DateTimeFormatterBuilder;
9+
import java.time.format.SignStyle;
10+
11+
public class YearMonthParamConverter extends TemporalParamConverter<YearMonth> {
12+
13+
// lifted from the JDK as PARSER is private...
14+
private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
15+
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
16+
.appendLiteral('-')
17+
.appendValue(MONTH_OF_YEAR, 2)
18+
.toFormatter();
19+
20+
// this can be called by generated code
21+
public YearMonthParamConverter() {
22+
super(PARSER);
23+
}
24+
25+
public YearMonthParamConverter(DateTimeFormatter formatter) {
26+
super(formatter);
27+
}
28+
29+
@Override
30+
protected YearMonth convert(String value) {
31+
return YearMonth.parse(value);
32+
}
33+
34+
@Override
35+
protected YearMonth convert(String value, DateTimeFormatter formatter) {
36+
return YearMonth.parse(value, formatter);
37+
}
38+
39+
public static class Supplier extends TemporalSupplier<YearMonthParamConverter> {
40+
41+
public Supplier() {
42+
}
43+
44+
public Supplier(String pattern, String dateTimeFormatterProviderClassName) {
45+
super(pattern, dateTimeFormatterProviderClassName);
46+
}
47+
48+
@Override
49+
protected YearMonthParamConverter createConverter(DateTimeFormatter dateTimeFormatter) {
50+
return new YearMonthParamConverter(dateTimeFormatter);
51+
}
52+
53+
@Override
54+
public String getClassName() {
55+
return YearMonthParamConverter.class.getName();
56+
}
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package org.jboss.resteasy.reactive.server.vertx.test.simple;
2+
3+
import java.time.YearMonth;
4+
import java.time.format.DateTimeFormatter;
5+
6+
import jakarta.ws.rs.CookieParam;
7+
import jakarta.ws.rs.FormParam;
8+
import jakarta.ws.rs.GET;
9+
import jakarta.ws.rs.HeaderParam;
10+
import jakarta.ws.rs.POST;
11+
import jakarta.ws.rs.Path;
12+
import jakarta.ws.rs.PathParam;
13+
import jakarta.ws.rs.QueryParam;
14+
15+
import org.hamcrest.Matchers;
16+
import org.jboss.resteasy.reactive.DateFormat;
17+
import org.jboss.resteasy.reactive.server.vertx.test.framework.ResteasyReactiveUnitTest;
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.extension.RegisterExtension;
20+
21+
import io.restassured.RestAssured;
22+
23+
public class YearMonthParamTest {
24+
25+
@RegisterExtension
26+
static ResteasyReactiveUnitTest test = new ResteasyReactiveUnitTest()
27+
.withApplicationRoot((jar) -> jar
28+
.addClasses(HelloResource.class, CustomDateTimeFormatterProvider.class));
29+
30+
@Test
31+
public void yearMonthAsQueryParam() {
32+
RestAssured.get("/hello?date=01984-12")
33+
.then().statusCode(200).body(Matchers.equalTo("hello#1984-12"));
34+
}
35+
36+
@Test
37+
public void yearMonthAsPathParam() {
38+
RestAssured.get("/hello/1821-01")
39+
.then().statusCode(200).body(Matchers.equalTo("hello@1821-01"));
40+
}
41+
42+
@Test
43+
public void yearMonthAsFormParam() {
44+
RestAssured.given().formParam("date", "995-06").post("/hello")
45+
.then().statusCode(200).body(Matchers.equalTo("hello:0995-06"));
46+
}
47+
48+
@Test
49+
public void yearMonthAsHeader() {
50+
RestAssured.with().header("date", "1984-11")
51+
.get("/hello/header")
52+
.then().statusCode(200).body(Matchers.equalTo("hello=1984-11"));
53+
}
54+
55+
@Test
56+
public void yearMonthAsCookie() {
57+
RestAssured.with().cookie("date", "1984-10")
58+
.get("/hello/cookie")
59+
.then().statusCode(200).body(Matchers.equalTo("hello/1984-10"));
60+
}
61+
62+
@Path("hello")
63+
public static class HelloResource {
64+
65+
@GET
66+
public String helloQuery(@QueryParam("date") @DateFormat(pattern = "yyyyy-MM") YearMonth date) {
67+
return "hello#" + date;
68+
}
69+
70+
@GET
71+
@Path("{date}")
72+
public String helloPath(@PathParam("date") YearMonth date) {
73+
return "hello@" + date;
74+
}
75+
76+
@POST
77+
public String helloForm(
78+
@FormParam("date") @DateFormat(dateTimeFormatterProvider = CustomDateTimeFormatterProvider.class) YearMonth date) {
79+
return "hello:" + date;
80+
}
81+
82+
@GET
83+
@Path("cookie")
84+
public String helloCookie(
85+
@CookieParam("date") YearMonth date) {
86+
return "hello/" + date;
87+
}
88+
89+
@GET
90+
@Path("header")
91+
public String helloHeader(
92+
@HeaderParam("date") YearMonth date) {
93+
return "hello=" + date;
94+
}
95+
}
96+
97+
public static class CustomDateTimeFormatterProvider implements DateFormat.DateTimeFormatterProvider {
98+
@Override
99+
public DateTimeFormatter get() {
100+
return DateTimeFormatter.ofPattern("yyy-MM");
101+
}
102+
}
103+
104+
}

0 commit comments

Comments
 (0)