Skip to content

Commit 4902c23

Browse files
authored
Fix recent timeseries OpenAPI schema (#1725)
## Summary While working with the TS recent method in cwmsjs I found an issue with the annotations. I.e. (Note if this change is brought in this will need to be regenerated on the generator) https://hydrologicengineeringcenter.github.io/cwms-data-api-client-javascript/classes/TimeSeriesApi.html#getTimeSeriesRecent.getTimeSeriesRecent-1 This fixes the OpenAPI response schema for `GET /timeseries/recent`. The controller returns and formats `List<RecentValue>`, but the OpenAPI annotation documented the `200` JSON response as `Tsv[]`. That caused generated clients to map the endpoint to the wrong model and drop the useful recent-value payload fields such as `id` and `dqu`. This updates the annotation to use `RecentValue[]` and adds a regression test to confirm the documented response type stays aligned with the controller behavior. ## Validation - Added a unit test asserting `TimeSeriesRecentController.handle` documents the `200` response as `RecentValue`. - Attempted to run: `.\gradlew.bat :cwms-data-api:test --tests cwms.cda.api.TimeSeriesControllerTest` - Local validation is currently blocked on Java 21 by a pre-existing compile issue in `TimeSeriesDaoImpl.java`, where unqualified `Record` is ambiguous between `org.jooq.Record` and `java.lang.Record`. - The PR CI currently runs on Java 11, where that ambiguity does not occur. Asked about possibly testing CI PR for java 21 as well. ## Checklist - [x] AI tools used
1 parent 99079d5 commit 4902c23

2 files changed

Lines changed: 20 additions & 3 deletions

File tree

cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesRecentController.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import cwms.cda.data.dao.TimeSeriesDao;
4646
import cwms.cda.data.dao.TimeSeriesDaoImpl;
4747
import cwms.cda.data.dto.RecentValue;
48-
import cwms.cda.data.dto.Tsv;
4948
import cwms.cda.formatters.ContentType;
5049
import cwms.cda.formatters.Formats;
5150
import io.javalin.core.util.Header;
@@ -117,7 +116,7 @@ private TimeSeriesDao getTimeSeriesDao(DSLContext dsl) {
117116
},
118117
responses = {
119118
@OpenApiResponse(status = STATUS_200, content = {
120-
@OpenApiContent(isArray = true, from = Tsv.class, type = Formats.JSON)}),
119+
@OpenApiContent(isArray = true, from = RecentValue.class, type = Formats.JSON)}),
121120
@OpenApiResponse(status = STATUS_404, description = "Based on the combination of "
122121
+ "inputs provided the timeseries group(s) were not found."),
123122
@OpenApiResponse(status = STATUS_501, description = "request format is not "

cwms-data-api/src/test/java/cwms/cda/api/TimeSeriesControllerTest.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@
22

33
import static org.junit.jupiter.api.Assertions.*;
44

5+
import cwms.cda.data.dto.RecentValue;
56
import cwms.cda.data.dto.TimeSeries;
67
import cwms.cda.formatters.ContentType;
78
import cwms.cda.formatters.Formats;
9+
import io.javalin.http.Context;
10+
import io.javalin.plugin.openapi.annotations.OpenApi;
11+
import io.javalin.plugin.openapi.annotations.OpenApiResponse;
812
import java.io.ByteArrayInputStream;
913
import java.io.InputStream;
14+
import java.lang.reflect.Method;
1015
import java.nio.charset.StandardCharsets;
1116
import java.sql.Timestamp;
1217
import java.time.Duration;
1318
import java.time.Instant;
1419
import java.time.ZonedDateTime;
20+
import java.util.Arrays;
1521
import java.util.List;
1622
import java.util.TimeZone;
1723

@@ -279,5 +285,17 @@ void testGetIds(){
279285

280286
}
281287

288+
@Test
289+
void testRecentOpenApiResponseUsesRecentValue() throws NoSuchMethodException {
290+
Method handle = TimeSeriesRecentController.class.getMethod("handle", Context.class);
291+
OpenApi openApi = handle.getAnnotation(OpenApi.class);
292+
OpenApiResponse okResponse = Arrays.stream(openApi.responses())
293+
.filter(response -> Controllers.STATUS_200.equals(response.status()))
294+
.findFirst()
295+
.orElseThrow();
296+
297+
assertEquals(1, okResponse.content().length);
298+
assertEquals(RecentValue.class, okResponse.content()[0].from());
299+
}
282300

283-
}
301+
}

0 commit comments

Comments
 (0)