From 36aa51b0e97073f466f296afbee6248cf30c1dd5 Mon Sep 17 00:00:00 2001 From: "Michael A. Neilson" Date: Tue, 29 Sep 2026 21:21:12 +0000 Subject: [PATCH 01/69] Compile worked targetting Java 17. --- buildSrc/src/main/groovy/cda.java-conventions.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/groovy/cda.java-conventions.gradle b/buildSrc/src/main/groovy/cda.java-conventions.gradle index 8fe281bb1..cdb04a461 100644 --- a/buildSrc/src/main/groovy/cda.java-conventions.gradle +++ b/buildSrc/src/main/groovy/cda.java-conventions.gradle @@ -14,8 +14,8 @@ eclipse { tasks.withType(JavaCompile) { options.encoding = "UTF-8" - sourceCompatibility = '11' - targetCompatibility = '11' + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } test { From a05e5b509ecc77bc932a79961702007ee96c7307 Mon Sep 17 00:00:00 2001 From: "Michael A. Neilson" Date: Tue, 29 Sep 2026 22:02:01 +0000 Subject: [PATCH 02/69] Start shifting annotations. --- cwms-data-api/build.gradle | 3 +- .../cwms/cda/api/LocationGroupController.java | 58 ++++++++++--------- .../java/cwms/cda/api/TurbineController.java | 43 ++++++++------ .../java/cwms/cda/api/UnitsController.java | 24 ++++---- .../api/UpstreamLocationsGetController.java | 19 +++--- .../cwms/cda/api/VerticalDatumController.java | 26 ++++----- gradle/libs.versions.toml | 9 ++- 7 files changed, 101 insertions(+), 81 deletions(-) diff --git a/cwms-data-api/build.gradle b/cwms-data-api/build.gradle index 9225da419..5c6088c5e 100644 --- a/cwms-data-api/build.gradle +++ b/cwms-data-api/build.gradle @@ -30,6 +30,7 @@ configurations.all { dependencies { annotationProcessor(libs.com.google.auto.service) + annotationProcessor(libs.javalin.openapi.annotation.processor) compileOnly(libs.com.google.auto.service.annotations) implementation(libs.jaxb.api) implementation(libs.jaxb.core) @@ -118,7 +119,7 @@ dependencies { exclude group: "org.eclipse.jetty" exclude group: "org.eclipse.jetty.websocket" } - implementation(libs.javalin.openapi) { + implementation(libs.bundles.javalin.openapi) { //exclude group: "org.eclipse.jetty" exclude group: "org.eclipse.jetty.websocket" exclude group: "jakarta.xml.bind", module: "*" diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java index 1f0185c8c..bd9756086 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java @@ -26,8 +26,6 @@ import static com.codahale.metrics.MetricRegistry.name; import static cwms.cda.api.Controllers.*; -import static cwms.cda.api.Controllers.queryParamAsClass; -import static cwms.cda.api.Controllers.requiredParam; import static cwms.cda.data.dao.JooqDao.getDslContext; import com.codahale.metrics.Histogram; @@ -44,15 +42,16 @@ import cwms.cda.formatters.Formats; import cwms.cda.formatters.csv.CsvV1LocationGroup; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.config.Key; +import io.javalin.http.Header; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import io.javalin.http.Context; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; import java.io.IOException; import java.util.HashMap; import java.util.List; @@ -102,11 +101,12 @@ private Timer.Context markAndTime(String subject) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, from = LocationGroup.class, type = Formats.JSON), - @OpenApiContent(isArray = true, from = CsvV1LocationGroup.class, type = Formats.CSV) + @OpenApiContent(from = LocationGroup[].class, type = Formats.JSON), + @OpenApiContent(from = CsvV1LocationGroup[].class, type = Formats.CSV) }) }, - description = "Returns CWMS Location Groups Data", tags = {TAG} + description = "Returns CWMS Location Groups Data", tags = {TAG}, + path = "/" ) @Override public void getAll(@NotNull Context ctx) { @@ -142,7 +142,7 @@ Boolean.class, false, metrics, name(LocationGroupController.class.getName(), byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { CdaError re = new CdaError("No location groups for office provided"); logger.atInfo().log("%s%nfor request %s", re, ctx.fullUrl()); @@ -184,7 +184,8 @@ Boolean.class, false, metrics, name(LocationGroupController.class.getName(), description = "Retrieves requested Location Group. This endpoint supports GEO JSON responses with " + Formats.GEOJSON + "." + "For more information about accept header usage, see this page.", - tags = {TAG} + tags = {TAG}, + path = "/" ) @Override public void getOne(@NotNull Context ctx, @NotNull String groupId) { @@ -206,7 +207,7 @@ public void getOne(@NotNull Context ctx, @NotNull String groupId) { contentType = new ContentType(Formats.GEOJSON); FeatureCollection fc = cdm.buildFeatureCollectionForLocationGroup(locationOfficeId, groupOfficeId, categoryOfficeId, categoryId, groupId, "EN"); - ObjectMapper mapper = ctx.appAttribute("ObjectMapper"); + ObjectMapper mapper = ctx.appData(new Key("ObjectMapper")); result = mapper.writeValueAsString(fc); } else { contentType = Formats.parseHeader(formatHeader, LocationGroup.class); @@ -229,7 +230,7 @@ public void getOne(@NotNull Context ctx, @NotNull String groupId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (JsonProcessingException e) { CdaError re = new CdaError("Failed to process request"); logger.atSevere().withCause(e).log("%s", re); @@ -252,15 +253,16 @@ public void getOne(@NotNull Context ctx, @NotNull String groupId) { @OpenApiParam(name = IGNORE_MISSING, description = "Specifies whether to fail when attempting " + "to assign a location that does not exist. Default is false.", type = Boolean.class) }, - method = HttpMethod.POST, - tags = {TAG} + methods = {HttpMethod.POST}, + tags = {TAG}, + path = "/" ) @Override public void create(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(formatHeader, LocationGroup.class); LocationGroup deserialize = Formats.parseContent(contentType, body, LocationGroup.class); @@ -287,7 +289,7 @@ public void create(@NotNull Context ctx) { sb.delete(sb.length() - 2, sb.length()); details.put("missing-locations", sb.toString()); if (ignoreMissing) { - ctx.status(HttpCode.MULTI_STATUS); + ctx.status(HttpStatus.MULTI_STATUS); } else { ctx.status(HttpServletResponse.SC_BAD_REQUEST); details.put("message", "One or more locations could not be assigned to the location group."); @@ -320,15 +322,16 @@ public void create(@NotNull Context ctx) { @OpenApiParam(name = IGNORE_MISSING, description = "Specifies whether to fail when attempting " + "to assign a location that does not exist. Default is false.", type = Boolean.class) }, - method = HttpMethod.PATCH, - tags = {TAG} + methods = {HttpMethod.PATCH}, + tags = {TAG}, + path = "/" ) @Override public void update(@NotNull Context ctx, @NotNull String groupId) { try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); String body = ctx.body(); String office = requiredParam(ctx, OFFICE); ContentType contentType = Formats.parseHeader(formatHeader, LocationGroup.class); @@ -350,7 +353,7 @@ public void update(@NotNull Context ctx, @NotNull String groupId) { Map details = new HashMap<>(); details.put("missing_locations", Formats.format(contentType, missingLocations, CwmsId.class)); if (ignoreMissing) { - ctx.status(HttpCode.MULTI_STATUS); + ctx.status(HttpStatus.MULTI_STATUS); } else { ctx.status(HttpServletResponse.SC_BAD_REQUEST); details.put("message", "One or more locations could not be assigned to the location group."); @@ -373,8 +376,9 @@ public void update(@NotNull Context ctx, @NotNull String groupId) { @OpenApiParam(name = CASCADE_DELETE, type = Boolean.class, description = "Specifies whether " + "to unassign any location assignments. Default: false"), }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/{location-id}" ) @Override public void delete(@NotNull Context ctx, @NotNull String groupId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TurbineController.java b/cwms-data-api/src/main/java/cwms/cda/api/TurbineController.java index 66dfadc80..c5df24808 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TurbineController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TurbineController.java @@ -56,14 +56,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -99,12 +99,13 @@ private Timer.Context markAndTime(String subject) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = Turbine.class), + @OpenApiContent(type = Formats.JSONV1, from = Turbine[].class), @OpenApiContent(from = Turbine.class, type = Formats.JSON) }) }, description = "Returns matching CWMS Turbine Data for a Reservoir Project.", - tags = {TAG} + tags = {TAG}, + path = "/" ) @Override public void getAll(Context ctx) { @@ -123,7 +124,7 @@ public void getAll(Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Turbines", ex); @@ -149,7 +150,8 @@ public void getAll(Context ctx) { }) }, description = "Returns CWMS Turbine Data", - tags = {TAG} + tags = {TAG}, + path = "/{name}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String name) { @@ -167,7 +169,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Turbine", ex); @@ -188,16 +190,17 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { description = "Create will fail if provided ID already exists. Default: true") }, description = "Create CWMS Turbine", - method = HttpMethod.POST, + methods = {HttpMethod.POST}, tags = {TAG}, responses = { @OpenApiResponse(status = STATUS_201, description = "Turbine successfully stored to CWMS.") - } + }, + path = "/" ) @Override public void create(Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Turbine.class); Turbine turbine = Formats.parseContent(contentType, ctx.body(), Turbine.class); turbine.validate(); @@ -223,11 +226,12 @@ public void create(Context ctx) { @OpenApiParam(name = NAME, required = true, description = "Specifies the new turbine name. ") }, description = "Rename CWMS Turbine", - method = HttpMethod.PATCH, + methods = {HttpMethod.PATCH}, tags = {TAG}, responses = { @OpenApiResponse(status = STATUS_200, description = "Turbine successfully renamed in to CWMS.") - } + }, + path = "/{name}" ) @Override public void update(@NotNull Context ctx, @NotNull String name) { @@ -255,13 +259,14 @@ public void update(@NotNull Context ctx, @NotNull String name) { type = JooqDao.DeleteMethod.class) }, description = "Delete CWMS Turbine", - method = HttpMethod.DELETE, + methods = {HttpMethod.DELETE}, tags = {TAG}, responses = { @OpenApiResponse(status = STATUS_200, description = "Turbine successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " + "inputs provided the turbine was not found.") - } + }, + path = "/{name}" ) @Override public void delete(@NotNull Context ctx, @NotNull String name) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/UnitsController.java b/cwms-data-api/src/main/java/cwms/cda/api/UnitsController.java index 3e207b9f8..6997e6cda 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/UnitsController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/UnitsController.java @@ -23,11 +23,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -52,13 +55,13 @@ private Timer.Context markAndTime(String subject) { return Controllers.markAndTime(metrics, getClass().getName(), subject); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(@NotNull Context ctx, @NotNull String unit) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -81,7 +84,8 @@ public void delete(@NotNull Context ctx, @NotNull String unit) { @OpenApiResponse(status = STATUS_501, description = "The format requested is not " + "implemented") }, - tags = {"Units"} + tags = {"Units"}, + path = "/" ) @Override public void getAll(@NotNull Context ctx) { @@ -121,7 +125,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError re = new CdaError("Failed to procees request to retrieve units"); LOGGER.atSevere().withCause(ex).log("Failed to process request to retrieve units"); @@ -129,7 +133,7 @@ public void getAll(@NotNull Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String unit) { @@ -138,7 +142,7 @@ public void getOne(@NotNull Context ctx, @NotNull String unit) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context ctx, @NotNull String unit) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/UpstreamLocationsGetController.java b/cwms-data-api/src/main/java/cwms/cda/api/UpstreamLocationsGetController.java index 435278cb7..67e75d60d 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/UpstreamLocationsGetController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/UpstreamLocationsGetController.java @@ -48,13 +48,15 @@ import cwms.cda.data.dto.stream.StreamLocation; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -89,10 +91,11 @@ private Timer.Context markAndTime(String subject) { @OpenApiParam(name = AREA_UNIT, description = "Area units."), }, responses = { - @OpenApiResponse(status = STATUS_200, content = {@OpenApiContent(isArray = true, type = Formats.JSONV1, from = StreamLocation.class)}) + @OpenApiResponse(status = STATUS_200, content = {@OpenApiContent(type = Formats.JSONV1, from = StreamLocation[].class)}) }, description = "Returns matching upstream stream locations.", - tags = {StreamLocationController.TAG} + tags = {StreamLocationController.TAG}, + path = "/" ) public void handle(@NotNull Context ctx) throws Exception { String locationId = ctx.pathParam(NAME); @@ -118,7 +121,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve upstream locations", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/VerticalDatumController.java b/cwms-data-api/src/main/java/cwms/cda/api/VerticalDatumController.java index 2bdc82aa2..7585a5ba6 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/VerticalDatumController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/VerticalDatumController.java @@ -50,14 +50,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -123,7 +123,7 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Vertical Datum Info", ex); @@ -144,7 +144,7 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { @OpenApiParam(name = OFFICE, required = true, description = "Specifies the owning office.") }, description = "Create Vertical Datum Info for a Location", - method = HttpMethod.POST, + methods = {HttpMethod.POST}, path = VDI_PATH, tags = {LOCATIONS_TAG}, responses = { @@ -154,7 +154,7 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { @Override public void create(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, VerticalDatumInfo.class); VerticalDatumInfo info = Formats.parseContent(contentType, ctx.body(), VerticalDatumInfo.class); //allow locationId and office to be specified in either the body or as query params, but require them to be present in one of those places @@ -189,7 +189,7 @@ public void create(@NotNull Context ctx) { @OpenApiParam(name = OFFICE, required = true, description = "Specifies the owning office.") }, description = "Update Vertical Datum Info for a Location", - method = HttpMethod.PATCH, + methods = {HttpMethod.PATCH}, path = VDI_PATH, tags = {LOCATIONS_TAG}, responses = { @@ -199,7 +199,7 @@ public void create(@NotNull Context ctx) { @Override public void update(@NotNull Context ctx, @NotNull String locationId) { try (Timer.Context ignored = markAndTime(UPDATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, VerticalDatumInfo.class); VerticalDatumInfo info = Formats.parseContent(contentType, ctx.body(), VerticalDatumInfo.class); //allow locationId and office to be specified in either the body or as query params, but require them to be present in one of those places @@ -224,7 +224,7 @@ public void update(@NotNull Context ctx, @NotNull String locationId) { @OpenApiParam(name = OFFICE, required = true, description = "Specifies the owning office.") }, description = "Delete Vertical Datum Info for a Location", - method = HttpMethod.DELETE, + methods = {HttpMethod.DELETE}, path = VDI_PATH, tags = {LOCATIONS_TAG}, responses = { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b331473f3..866d0b3da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ logback = "1.5.34" google-findbugs = "3.0.2" error_prone_annotations = "2.15.0" cwms-ratings = "4.2.3" -javalin = "4.6.8" +javalin = "7.2.3" tomcat = "9.0.121" swagger-core = "2.2.23" jackson = "2.22.2" @@ -85,7 +85,9 @@ cwms-ratings-io-jdbc = { module = "mil.army.usace.hec:hec-cwms-ratings-io-jdbc", owasp-sanitizer = { module = "com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer", version.ref = "owasp" } geojson-jackson = { module = "de.grundid.opendatalab:geojson-jackson", version.ref = "geojson-jackson" } javalin-core = { module = "io.javalin:javalin", version.ref = "javalin" } -javalin-openapi = { module = "io.javalin:javalin-openapi", version.ref = "javalin" } +javalin-openapi-annotation-processor = { module = "io.javalin.community.openapi:openapi-annotation-processor", version="javalin" } +javalin-openapi-api = { module = "io.javalin.community.openapi:javalin-openapi-plugin", version.ref = "javalin" } +javalin-openapi-swagger = { module = "io.javalin.community.openapi:javalin-openapi-plugin", version.ref = "javalin" } swagger-core = { module = "io.swagger.core.v3:swagger-core", version.ref = "swagger-core" } metrics-core = { module = "io.dropwizard.metrics:metrics-core", version.ref = "dropwizard" } metrics-servlets = { module = "io.dropwizard.metrics:metrics-servlets", version.ref = "dropwizard" } @@ -167,4 +169,5 @@ testcontainers = [ "testcontainers-base", "testcontainers-database-commons", "te metrics = ["metrics-core", "metrics-servlets", "metrics-prometheus-client", "metrics-prometheus-servlets" ] jackson = ["jackson-core", "jackson-dataformat-csv", "jackson-dataformat-xml", "jackson-datatype-jsr310" ] overrides = ["io-github.classgraph", "io-swagger-parser"] -java-parser = ["javaparser-core", "javaparser-symbol-solver-core"] \ No newline at end of file +java-parser = ["javaparser-core", "javaparser-symbol-solver-core"] +javalin-openapi = ["javalin-openapi-api", "javalin-openapi-swagger"] \ No newline at end of file From aafea8551949e44b2acb56d46abc7fcff70775ab Mon Sep 17 00:00:00 2001 From: "Michael A. Neilson" Date: Wed, 30 Sep 2026 13:43:39 +0000 Subject: [PATCH 03/69] Batch of controllers. --- .../cda/api/TimeSeriesFilteredController.java | 24 +++++------ ...eSeriesIdentifierDescriptorController.java | 39 ++++++++++-------- .../cda/api/TimeSeriesRecentController.java | 24 +++++------ .../cda/api/TimeSeriesVersionsController.java | 13 +++--- .../java/cwms/cda/api/TimeZoneController.java | 23 ++++++----- .../api/TurbineChangesDeleteController.java | 11 ++--- .../cda/api/TurbineChangesGetController.java | 17 ++++---- .../cda/api/TurbineChangesPostController.java | 41 ++++--------------- .../java/cwms/cda/api/UnitsController.java | 3 -- .../api/UpstreamLocationsGetController.java | 2 - 10 files changed, 88 insertions(+), 109 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesFilteredController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesFilteredController.java index ea144fe66..2f6be7495 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesFilteredController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesFilteredController.java @@ -19,15 +19,15 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import cwms.cda.helpers.DateUtils; -import io.javalin.core.util.Header; -import io.javalin.core.validation.Validator; +import io.javalin.http.Header; +import io.javalin.validation.Validator; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -167,7 +167,7 @@ private TimeSeriesDao getTimeSeriesDao(DSLContext dsl) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.GET, + methods = {HttpMethod.GET}, path = "/timeseries/filtered", tags = TAG ) @@ -247,7 +247,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IllegalArgumentException ex) { CdaError re = new CdaError("Invalid arguments supplied"); logger.atSevere().withCause(ex).log("%s", re); @@ -284,8 +284,8 @@ private void addLinkHeader(@NotNull Context ctx, FilteredTimeSeries fts, Content } public String buildRequestUrl(Context ctx, String cursor) throws URISyntaxException { - URIBuilder builder = new URIBuilder(ctx.req.getRequestURL().toString()); // requestURL stops just before ? - builder.setParameters(URLEncodedUtils.parse(ctx.req.getQueryString(), StandardCharsets.UTF_8)); + URIBuilder builder = new URIBuilder(ctx.url()); // requestURL stops just before ? + builder.setParameters(URLEncodedUtils.parse(ctx.queryString(), StandardCharsets.UTF_8)); // override or add the paging cursor if (cursor != null && !cursor.isEmpty()) { @@ -294,6 +294,4 @@ public String buildRequestUrl(Context ctx, String cursor) throws URISyntaxExcept return builder.build().toString(); } - - } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesIdentifierDescriptorController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesIdentifierDescriptorController.java index 5d9055948..e1066a154 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesIdentifierDescriptorController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesIdentifierDescriptorController.java @@ -40,14 +40,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -114,7 +114,8 @@ protected DSLContext getDslContext(Context ctx) { + "implemented")}, description = "Returns CWMS timeseries identifier descriptor" + "Data. Currently includes aliased items in results.", - tags = {TAG} + tags = {TAG}, + path = "/timeseries/identifier" ) @Override public void getAll(Context ctx) { @@ -149,7 +150,7 @@ public void getAll(Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve timeseries identifiers", ex); @@ -180,7 +181,8 @@ public void getAll(Context ctx) { @OpenApiResponse(status = STATUS_501, description = "request format is not " + "implemented")}, description = "Retrieves requested timeseries identifier descriptor", - tags = {TAG} + tags = {TAG}, + path = "/timeseries/identifier/{timeseriesId}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String timeseriesId) { @@ -210,7 +212,7 @@ public void getOne(@NotNull Context ctx, @NotNull String timeseriesId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { CdaError re = new CdaError("Unable to find identifier based on parameters " + "given"); @@ -237,15 +239,16 @@ public void getOne(@NotNull Context ctx, @NotNull String timeseriesId) { @OpenApiParam(name = FAIL_IF_EXISTS, type = Boolean.class, description = "Create will fail if provided ID already exists. Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = {HttpMethod.POST}, + tags = {TAG}, + path = "/timeseries/identifier" ) @Override public void create(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(formatHeader, TimeSeriesIdentifierDescriptor.class); @@ -288,7 +291,8 @@ public void create(@NotNull Context ctx) { + "that data will be considered to be on time."), @OpenApiParam(name = ACTIVE, type = Boolean.class, description = "'True' or 'true' if the time series is active") - }, tags = {TAG} + }, tags = {TAG}, + path = "/timeseries/identitifer/{name}" ) @Override public void update(@NotNull Context ctx, @NotNull String name) { @@ -341,8 +345,9 @@ public void update(@NotNull Context ctx, @NotNull String name) { type = JooqDao.DeleteMethod.class) }, description = "Deletes requested timeseries identifier", - method = HttpMethod.DELETE, - tags = {TAG} + methods = {HttpMethod.DELETE}, + tags = {TAG}, + path = "/timeseries/identifier/{timeseriesId}" ) @Override public void delete(@NotNull Context ctx, @NotNull String timeseriesId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesRecentController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesRecentController.java index 39d4895ef..c12c36487 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesRecentController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesRecentController.java @@ -49,14 +49,14 @@ import cwms.cda.data.dto.RecentValue; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.sql.Timestamp; import java.util.ArrayList; @@ -118,7 +118,7 @@ private TimeSeriesDao getTimeSeriesDao(DSLContext dsl) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, from = RecentValue.class, type = Formats.JSON)}), + @OpenApiContent(from = RecentValue[].class, type = Formats.JSON)}), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " + "inputs provided the timeseries group(s) were not found."), @OpenApiResponse(status = STATUS_501, description = "request format is not " @@ -127,15 +127,15 @@ private TimeSeriesDao getTimeSeriesDao(DSLContext dsl) { path = "/timeseries/recent", description = "Returns CWMS Timeseries Groups Data", tags = TimeSeriesController.TAG, - method = HttpMethod.GET + methods = {HttpMethod.GET} ) public void handle(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime("getRecent")) { String office = ctx.queryParam(OFFICE); - String categoryId = ctx.queryParamAsClass(CATEGORY_ID, String.class).allowNullable().get(); - String groupId = ctx.queryParamAsClass(GROUP_ID, String.class).allowNullable().get(); - String tsIdsParam = ctx.queryParamAsClass(TS_IDS, String.class).allowNullable().get(); + String categoryId = ctx.queryParamAsClass(CATEGORY_ID, String.class).getOrNull(); + String groupId = ctx.queryParamAsClass(GROUP_ID, String.class).getOrNull(); + String tsIdsParam = ctx.queryParamAsClass(TS_IDS, String.class).getOrNull(); UnitSystem unitSystem = ctx.queryParamAsClass(UNIT_SYSTEM, UnitSystem.class) .getOrDefault(UnitSystem.EN); @@ -194,7 +194,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Timeseries Recents", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesVersionsController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesVersionsController.java index 08feb8ac4..b062d65c9 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesVersionsController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesVersionsController.java @@ -52,13 +52,13 @@ import cwms.cda.data.dto.TimeSeriesVersions; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.time.Instant; import javax.servlet.http.HttpServletResponse; @@ -119,7 +119,8 @@ private TimeSeriesDao getTimeSeriesDao(DSLContext dsl) { @OpenApiContent(type = Formats.JSONV1, from = TimeSeriesVersions.class) }) }, - tags = {TimeSeriesController.TAG} + tags = {TimeSeriesController.TAG}, + path = "/" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeZoneController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeZoneController.java index f747c3287..7be510d69 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeZoneController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeZoneController.java @@ -23,12 +23,12 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -52,13 +52,13 @@ private Timer.Context markAndTime(String subject) { return Controllers.markAndTime(metrics, getClass().getName(), subject); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(@NotNull Context ctx, @NotNull String id) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -84,7 +84,8 @@ public void delete(@NotNull Context ctx, @NotNull String id) { @OpenApiResponse(status = STATUS_501, description = "The format requested is not " + "implemented") }, - tags = {"TimeZones"} + tags = {"TimeZones"}, + path = "/timezone" ) @Override public void getAll(@NotNull Context ctx) { @@ -122,7 +123,7 @@ public void getAll(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_OK); byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError re = new CdaError("Failed to process request to retrieve time zone"); LOGGER.atSevere().withCause(ex).log("Failed to process request to retrieve time zone"); @@ -130,13 +131,13 @@ public void getAll(@NotNull Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String id) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context ctx, @NotNull String id) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesDeleteController.java b/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesDeleteController.java index 15cbf4ca9..2536d6e51 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesDeleteController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesDeleteController.java @@ -37,10 +37,10 @@ import cwms.cda.helpers.annotations.IgnoreRequiredQueryParamMismatch; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.time.Instant; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -84,8 +84,9 @@ private Timer.Context markAndTime(String subject) { + "Default is False") }, description = "Delete CWMS Turbine Changes", - method = HttpMethod.DELETE, + methods = {HttpMethod.DELETE}, tags = {TurbineController.TAG}, + path = "", responses = { @OpenApiResponse(status = STATUS_200, description = "Turbine successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesGetController.java b/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesGetController.java index a4a810861..8c5bdfc64 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesGetController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesGetController.java @@ -54,13 +54,13 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import cwms.cda.helpers.annotations.IgnoreRequiredQueryParamMismatch; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.time.Instant; import java.util.List; @@ -124,11 +124,12 @@ private Timer.Context markAndTime(String subject) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = TurbineChange.class) + @OpenApiContent(type = Formats.JSONV1, from = TurbineChange[].class) }) }, description = "Returns matching CWMS Turbine Change Data for a Reservoir Project.", - tags = {TurbineController.TAG} + tags = {TurbineController.TAG}, + path = "" ) @IgnoreRequiredQueryParamMismatch(parameterNames = {TIMEZONE}) public void handle(@NotNull Context ctx) throws Exception { @@ -162,7 +163,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Turbine Changes", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesPostController.java b/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesPostController.java index 533f93044..940df4b3e 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesPostController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TurbineChangesPostController.java @@ -24,52 +24,28 @@ package cwms.cda.api; -import static com.codahale.metrics.MetricRegistry.name; -import static cwms.cda.api.Controllers.BEGIN; import static cwms.cda.api.Controllers.CREATE; -import static cwms.cda.api.Controllers.DELETE; -import static cwms.cda.api.Controllers.END; -import static cwms.cda.api.Controllers.END_TIME_INCLUSIVE; -import static cwms.cda.api.Controllers.GET_ALL; import static cwms.cda.api.Controllers.NAME; import static cwms.cda.api.Controllers.OFFICE; import static cwms.cda.api.Controllers.OVERRIDE_PROTECTION; -import static cwms.cda.api.Controllers.PAGE_SIZE; -import static cwms.cda.api.Controllers.PROJECT_ID; -import static cwms.cda.api.Controllers.RESULTS; -import static cwms.cda.api.Controllers.SIZE; -import static cwms.cda.api.Controllers.START_TIME_INCLUSIVE; -import static cwms.cda.api.Controllers.STATUS_200; import static cwms.cda.api.Controllers.STATUS_201; -import static cwms.cda.api.Controllers.STATUS_204; import static cwms.cda.api.Controllers.STATUS_404; -import static cwms.cda.api.Controllers.UNIT_SYSTEM; -import static cwms.cda.api.Controllers.requiredInstant; -import static cwms.cda.api.Controllers.requiredParam; import static cwms.cda.data.dao.JooqDao.getDslContext; -import com.codahale.metrics.Histogram; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; -import cwms.cda.api.enums.UnitSystem; -import cwms.cda.api.errors.CdaError; import cwms.cda.data.dao.location.kind.TurbineDao; -import cwms.cda.data.dto.CwmsId; import cwms.cda.data.dto.StatusResponse; import cwms.cda.data.dto.location.kind.TurbineChange; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; import io.javalin.http.Context; -import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import java.time.Instant; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -101,8 +77,9 @@ public TurbineChangesPostController(MetricRegistry metrics) { + "Default is False") }, description = "Create CWMS Turbine Changes", - method = HttpMethod.POST, + methods = {HttpMethod.POST}, tags = {TurbineController.TAG}, + path = "/", responses = { @OpenApiResponse(status = STATUS_201, description = "Turbine successfully stored to CWMS."), @OpenApiResponse(status = STATUS_404, description = "Project Id or Turbine location Ids not found.") @@ -114,7 +91,7 @@ public void handle(@NotNull Context ctx) throws Exception { logUnusedPathParameter(ctx, OFFICE, "Body contains required information."); try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, TurbineChange.class); List turbine = Formats.parseContentList(contentType, ctx.body(), TurbineChange.class); boolean overrideProtection = ctx.queryParamAsClass(OVERRIDE_PROTECTION, Boolean.class) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/UnitsController.java b/cwms-data-api/src/main/java/cwms/cda/api/UnitsController.java index 6997e6cda..20e99db5f 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/UnitsController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/UnitsController.java @@ -26,10 +26,7 @@ import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.openapi.OpenApi; -import io.javalin.openapi.HttpMethod; -import io.javalin.openapi.OpenApiContent; import io.javalin.openapi.OpenApiParam; -import io.javalin.openapi.OpenApiRequestBody; import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; diff --git a/cwms-data-api/src/main/java/cwms/cda/api/UpstreamLocationsGetController.java b/cwms-data-api/src/main/java/cwms/cda/api/UpstreamLocationsGetController.java index 67e75d60d..02c21d44c 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/UpstreamLocationsGetController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/UpstreamLocationsGetController.java @@ -52,10 +52,8 @@ import io.javalin.http.Context; import io.javalin.http.Handler; import io.javalin.openapi.OpenApi; -import io.javalin.openapi.HttpMethod; import io.javalin.openapi.OpenApiContent; import io.javalin.openapi.OpenApiParam; -import io.javalin.openapi.OpenApiRequestBody; import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; From 3d6b7f49760f5cc4e6de13373b54d54071e6d806 Mon Sep 17 00:00:00 2001 From: "Michael A. Neilson" Date: Wed, 30 Sep 2026 19:41:03 +0000 Subject: [PATCH 04/69] Batch of controllers. --- .../src/main/java/cwms/cda/ApiServlet.java | 2 + .../java/cwms/cda/api/BasinController.java | 38 +++++++------ .../cda/api/BinaryTimeSeriesController.java | 40 ++++++------- .../api/BinaryTimeSeriesValueController.java | 18 +++--- .../java/cwms/cda/api/BlobController.java | 53 +++++++++-------- .../java/cwms/cda/api/CatalogController.java | 35 ++++++------ .../java/cwms/cda/api/CdaVersionHandler.java | 14 ++--- .../java/cwms/cda/api/ClobController.java | 57 ++++++++++--------- .../main/java/cwms/cda/api/Controllers.java | 21 +++---- .../java/cwms/cda/api/CountyController.java | 24 ++++---- .../api/DownstreamLocationsGetController.java | 17 +++--- .../cwms/cda/api/EmbankmentController.java | 46 ++++++++------- .../java/cwms/cda/api/EntityController.java | 43 +++++++------- .../cwms/cda/api/LevelRefsController.java | 15 ++--- .../cda/api/LevelsAsTimeSeriesController.java | 14 ++--- .../java/cwms/cda/api/LevelsController.java | 47 +++++++-------- .../cda/api/LocationCategoryController.java | 42 +++++++------- .../java/cwms/cda/api/LocationController.java | 46 ++++++++------- .../cwms/cda/api/LocationGroupController.java | 10 ++-- .../cwms/cda/api/LocationKindController.java | 20 ++++--- .../cwms/cda/api/LookupTypeController.java | 36 ++++++------ .../cwms/cda/api/MeasurementController.java | 44 +++++++------- .../MeasurementTimeExtentsGetController.java | 17 +++--- .../java/cwms/cda/api/OfficeController.java | 28 ++++----- .../cwms/cda/api/ParametersController.java | 29 +++++----- .../java/cwms/cda/api/PoolController.java | 35 ++++++------ .../java/cwms/cda/api/ProjectController.java | 42 +++++++------- .../java/cwms/cda/api/PropertyController.java | 42 +++++++------- .../cwms/cda/api/PublishedController.java | 27 ++++----- .../java/cwms/cda/api/RangeRequestUtil.java | 21 ++++--- .../cda/api/SpecifiedLevelController.java | 40 +++++++------ .../cwms/cda/api/StandardTextController.java | 43 +++++++------- .../java/cwms/cda/api/StateController.java | 23 ++++---- .../java/cwms/cda/api/StreamController.java | 52 +++++++++-------- .../cda/api/StreamLocationController.java | 45 ++++++++------- .../cwms/cda/api/StreamReachController.java | 43 +++++++------- .../cda/api/TimeSeriesCategoryController.java | 46 ++++++++------- .../cwms/cda/api/TimeSeriesController.java | 54 +++++++++--------- 38 files changed, 673 insertions(+), 596 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java index c33958408..44bb43e68 100644 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java +++ b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java @@ -59,6 +59,7 @@ import io.javalin.http.JavalinServlet; import io.javalin.plugin.openapi.OpenApiOptions; import io.javalin.plugin.openapi.OpenApiPlugin; +import io.javalin.validation.Validator; import io.opentelemetry.api.trace.Span; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; @@ -205,6 +206,7 @@ public void init(ServletConfig config) throws ServletException { @Override public void init() { logger.atInfo().log("Initializing Javalin."); + JavalinValidation.register(UnitSystem.class, UnitSystem::systemFor); JavalinValidation.register(JooqDao.DeleteMethod.class, Controllers::getDeleteMethod); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/BasinController.java b/cwms-data-api/src/main/java/cwms/cda/api/BasinController.java index 56f4afec8..3ac55f9dc 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/BasinController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/BasinController.java @@ -52,13 +52,13 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.sql.SQLException; import java.util.Collections; @@ -113,7 +113,8 @@ private Timer.Context markAndTime(String subject) { description = "Returns CWMS Basin Data. " + "This endpoint handles multiple accept header types, including named pg json. " + "For more information about accept header usage, see this page.", - tags = {TAG} + tags = {TAG}, + path = "/basins" ) @Override public void getAll(@NotNull Context ctx) { @@ -147,7 +148,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (SQLException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Error retrieving all basins", ex); LOGGER.atSevere().withCause(ex).log("Error retrieving all basins"); @@ -193,7 +194,8 @@ public void getAll(@NotNull Context ctx) { description = "Returns CWMS Basin Data. " + "This endpoint handles multiple accept header types, including named pg json. " + "For more information about accept header usage, see this page.", - tags = {TAG} + tags = {TAG}, + path = "/basins/{" + NAME + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String name) { @@ -226,7 +228,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Basin", ex); LOGGER.atSevere().withCause(ex).log("Failed to process request to retrieve Basin"); @@ -250,9 +252,11 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, description = "Renames CWMS Basin", - tags = {TAG} + tags = {TAG}, + path = "/basins/{" + NAME + "}" + ) @Override public void update(@NotNull Context ctx, @NotNull String name) { @@ -278,14 +282,15 @@ public void update(@NotNull Context ctx, @NotNull String name) { @OpenApiResponse(status = STATUS_204, description = "Basin successfully stored to CWMS."), @OpenApiResponse(status = STATUS_501, description = "Requested format is not implemented") }, - method = HttpMethod.POST, + methods = HttpMethod.POST, description = "Creates CWMS Basin", - tags = {TAG} + tags = {TAG}, + path = "/basins/" ) @Override public void create(@NotNull Context ctx) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, cwms.cda.data.dto.basin.Basin.class); ctx.contentType(contentType.toString()); @@ -312,7 +317,8 @@ public void create(@NotNull Context ctx) { + "the basin to be deleted.") }, description = "Deletes CWMS Basin", - tags = {TAG} + tags = {TAG}, + path = "/basins/{" + NAME + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String name) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesController.java b/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesController.java index f1380fb03..7d1191f89 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesController.java @@ -51,14 +51,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import cwms.cda.helpers.ReplaceUtils; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.net.URISyntaxException; import java.net.URLEncoder; @@ -117,7 +117,8 @@ protected TimeSeriesBinaryDao getDao(DSLContext dsl) { @OpenApiContent(type = Formats.JSONV2, from = BinaryTimeSeries.class) } )}, - tags = {TAG} + tags = {TAG}, + path = "/timeseries/binary" ) @Override public void getAll(@NotNull Context ctx) { @@ -163,7 +164,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (URISyntaxException | IOException ex) { CdaError re = ExceptionTraceSupport.buildError(ctx, "Failed to process request: " + ex.getLocalizedMessage(), ex); @@ -172,7 +173,7 @@ public void getAll(@NotNull Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String templateId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -188,15 +189,16 @@ public void getOne(@NotNull Context ctx, @NotNull String templateId) { queryParams = { @OpenApiParam(name = REPLACE_ALL, type = Boolean.class) }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/timeseries/binary" ) @Override public void create(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, BinaryTimeSeries.class); BinaryTimeSeries tts = deserializeBody(ctx, contentType); TimeSeriesBinaryDao dao = getDao(dsl); @@ -223,7 +225,7 @@ public void create(@NotNull Context ctx) { }, required = true ), - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, path = "/timeseries/binary/{timeseries}", tags = {TAG} ) @@ -233,7 +235,7 @@ public void update(@NotNull Context ctx, @NotNull String name) { try (Timer.Context ignored = markAndTime(UPDATE)) { boolean maxVersion = true; boolean replaceAll = ctx.queryParamAsClass(REPLACE_ALL, Boolean.class).getOrDefault(false); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, BinaryTimeSeries.class); BinaryTimeSeries tts = deserializeBody(ctx, contentType); DSLContext dsl = getDslContext(ctx); @@ -244,7 +246,6 @@ public void update(@NotNull Context ctx, @NotNull String name) { } } - @OpenApi( description = "Deletes requested binary timeseries id", pathParams = { @@ -268,8 +269,9 @@ public void update(@NotNull Context ctx, @NotNull String name) { @OpenApiParam(name = VERSION_DATE, description = "The version date for the time " + "series. If not specified, the maximum version date is used.") }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/timeseries/binary/{" + NAME + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String name) { @@ -320,6 +322,6 @@ Body greater than max size (1000000 bytes) We know this end-point can potentially deal with big bodies so the solution is just read the object from the body as an input stream. */ - return Formats.parseContent(contentType, ctx.bodyAsInputStream(), BinaryTimeSeries.class); + return Formats.parseContent(contentType, ctx.bodyInputStream(), BinaryTimeSeries.class); } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesValueController.java b/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesValueController.java index 798bb5806..32bf79ba6 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesValueController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesValueController.java @@ -24,26 +24,23 @@ package cwms.cda.api; -import com.codahale.metrics.Histogram; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.google.common.flogger.FluentLogger; import cwms.cda.api.errors.CdaError; import cwms.cda.data.dao.BlobDao; import cwms.cda.data.dao.StreamConsumer; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; import javax.servlet.http.HttpServletResponse; -import static com.codahale.metrics.MetricRegistry.name; import static cwms.cda.api.Controllers.*; import static cwms.cda.data.dao.JooqDao.getDslContext; @@ -73,7 +70,8 @@ public BinaryTimeSeriesValueController(MetricRegistry metrics) { @OpenApiContent(from = byte[].class) } )}, - tags = {BinaryTimeSeriesController.TAG} + tags = {BinaryTimeSeriesController.TAG}, + path = "/timeseries/binary/{" + NAME + "}/value" ) public void handle(@NotNull Context ctx) { //Implementation will change with new CWMS schema @@ -89,7 +87,7 @@ public void handle(@NotNull Context ctx) { final Long offset; final Long end ; - long[] ranges = RangeParser.parseFirstRange(ctx.header(io.javalin.core.util.Header.RANGE)); + long[] ranges = RangeParser.parseFirstRange(ctx.header(Header.RANGE)); if (ranges != null) { offset = ranges[0]; end = ranges[1]; diff --git a/cwms-data-api/src/main/java/cwms/cda/api/BlobController.java b/cwms-data-api/src/main/java/cwms/cda/api/BlobController.java index 60f5c4097..155f5d821 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/BlobController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/BlobController.java @@ -35,15 +35,15 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import cwms.cda.formatters.FormattingException; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.Optional; import javax.servlet.http.HttpServletResponse; @@ -116,7 +116,8 @@ private BlobAccess chooseBlobAccess(DSLContext dsl) { @OpenApiContent(type = Formats.JSONV2, from = Blobs.class), }) }, - tags = {TAG} + tags = {TAG}, + path = "/blobs" ) @Override public void getAll(@NotNull Context ctx) { @@ -130,7 +131,7 @@ public void getAll(@NotNull Context ctx) { if (!CwmsDTOPaginated.CURSOR_CHECK.invoke(cursor)) { ctx.json(new CdaError("cursor or page passed in but failed validation")) - .status(HttpCode.BAD_REQUEST); + .status(HttpStatus.BAD_REQUEST); return; } @@ -155,7 +156,7 @@ Integer.class, DEFAULT_PAGE_SIZE, getMetrics(), byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Blobs", ex); LOGGER.atSevere().withCause(ex).log("Failed to process request to retrieve Blobs"); @@ -190,7 +191,8 @@ Integer.class, DEFAULT_PAGE_SIZE, getMetrics(), @OpenApiContent(type = "application/octet-stream", from = byte[].class) }) }, - tags = {TAG} + tags = {TAG}, + path = "/blob/{" + BLOB_ID + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String blobId) { @@ -209,7 +211,7 @@ public void getOne(@NotNull Context ctx, @NotNull String blobId) { final Long offset; final Long end; - long[] ranges = RangeParser.parseFirstRange(ctx.header(io.javalin.core.util.Header.RANGE)); + long[] ranges = RangeParser.parseFirstRange(ctx.header(Header.RANGE)); if (ranges != null) { offset = ranges[0]; end = ranges[1]; @@ -251,20 +253,21 @@ public void getOne(@NotNull Context ctx, @NotNull String blobId) { @OpenApiParam(name = FAIL_IF_EXISTS, type = Boolean.class, description = "Create will fail if provided ID already exists. Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/blobs" ) @Override public void create(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); ContentType contentType = Formats.parseHeader(formatHeader, Blob.class); - Blob blob = Formats.parseContent(contentType, ctx.bodyAsInputStream(), Blob.class); + Blob blob = Formats.parseContent(contentType, ctx.bodyInputStream(), Blob.class); BlobAccess dao = chooseBlobAccess(dsl); dao.create(blob, failIfExists, false); - ctx.status(HttpCode.CREATED); + ctx.status(HttpStatus.CREATED); } } @@ -287,8 +290,9 @@ public void create(@NotNull Context ctx) { + "We will likely add support for encoding the ID in the path in the future. For now use the id field for those IDs. " + "Client libraries should detect slashes and choose the appropriate field. \"ignored\" is suggested for the path endpoint."), }, - method = HttpMethod.PATCH, - tags = {TAG} + methods = HttpMethod.PATCH, + tags = {TAG}, + path = "/blob/{" + BLOB_ID + "}" ) @Override public void update(@NotNull Context ctx, @NotNull String blobId) { @@ -301,11 +305,11 @@ public void update(@NotNull Context ctx, @NotNull String blobId) { } DSLContext dsl = getDslContext(ctx); - String reqContentType = ctx.req.getContentType(); + String reqContentType = ctx.contentType(); String formatHeader = reqContentType != null ? reqContentType : Formats.JSON; ContentType contentType = Formats.parseHeader(formatHeader, Blob.class); - Blob blob = Formats.parseContent(contentType, ctx.bodyAsInputStream(), Blob.class); + Blob blob = Formats.parseContent(contentType, ctx.bodyInputStream(), Blob.class); if (blob.getOfficeId() == null) { throw new FormattingException("An officeId is required when updating a blob"); @@ -347,8 +351,9 @@ public void update(@NotNull Context ctx, @NotNull String blobId) { + "We will likely add support for encoding the ID in the path in the future. For now use the id field for those IDs. " + "Client libraries should detect slashes and choose the appropriate field. \"ignored\" is suggested for the path endpoint."), }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/blobs/{" + BLOB_ID + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String blobId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/CatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/CatalogController.java index 4f964e40b..9e253d0ce 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/CatalogController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/CatalogController.java @@ -48,13 +48,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.config.Key; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -113,19 +114,19 @@ private Timer.Context markAndTime(String subject) { return Controllers.markAndTime(metrics, getClass().getName(), subject); } - @OpenApi(tags = {TAG}, ignore = true) + @OpenApi(tags = {TAG}, ignore = true, path = "") @Override public void create(Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(tags = {"Catalog"}, ignore = true) + @OpenApi(tags = {"Catalog"}, ignore = true, path = "") @Override public void delete(Context ctx, @NotNull String entry) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(tags = {"Catalog"}, ignore = true) + @OpenApi(tags = {"Catalog"}, ignore = true, path = "") @Override public void getAll(Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -255,7 +256,8 @@ public void getAll(Context ctx) { @OpenApiContent(from = Catalog.class, type = Formats.XML) }) }, - tags = {TAG} + tags = {TAG}, + path = "/catalog/{dataset}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String dataSet) { @@ -263,8 +265,7 @@ public void getOne(@NotNull Context ctx, @NotNull String dataSet) { try (final Timer.Context ignored = markAndTime(GET_ONE)) { DSLContext dsl = JooqDao.getDslContext(ctx); - String valDataSet = - ((PolicyFactory) ctx.appAttribute("PolicyFactory")).sanitize(dataSet); + String valDataSet = ctx.appData(new Key("PolicyFactory")).sanitize(dataSet); // TODO: key constant String cursor = queryParamAsClass(ctx, new String[] {PAGE, CURSOR}, String.class, "", metrics, name(CatalogController.class.getName(), GET_ONE)); @@ -278,9 +279,9 @@ public void getOne(@NotNull Context ctx, @NotNull String dataSet) { String.class, UnitSystem.SI.getValue(), metrics, name(CatalogController.class.getName(), GET_ONE)); - String office = ctx.queryParamAsClass(OFFICE, String.class).allowNullable() + String office = ctx.queryParamAsClass(OFFICE, String.class) .check(Office::validOfficeCanNull, "Invalid office provided") - .get(); + .getOrNull(); String like = ctx.queryParamAsClass(LIKE, String.class).getOrDefault(".*"); @@ -379,13 +380,13 @@ public void getOne(@NotNull Context ctx, @NotNull String dataSet) { byte[] bytes = data.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { final CdaError re = new CdaError("Cannot create catalog of requested " + "information"); logger.atInfo().log("%s with url:%s", re, ctx.fullUrl()); - ctx.json(re).status(HttpCode.NOT_FOUND); + ctx.json(re).status(HttpStatus.NOT_FOUND); } } catch (IOException ex) { CdaError re = new CdaError("Failed to process request to retrieve catalog"); @@ -465,7 +466,7 @@ private static String validateSearchText(String searchText) { return trimmed; } - @OpenApi(tags = {"Catalog"}, ignore = true) + @OpenApi(tags = {"Catalog"}, ignore = true, path = "") @Override public void update(Context ctx, @NotNull String entry) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/CdaVersionHandler.java b/cwms-data-api/src/main/java/cwms/cda/api/CdaVersionHandler.java index e8ed2b0a5..55a735947 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/CdaVersionHandler.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/CdaVersionHandler.java @@ -39,13 +39,13 @@ import cwms.cda.data.dto.CdaVersion; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -72,7 +72,7 @@ private Timer.Context markAndTime(String subject) { }, tags = {TAG}, path = "/version", - method = HttpMethod.GET + methods = HttpMethod.GET ) @Override public void handle(@NotNull Context ctx) throws Exception { @@ -86,7 +86,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve CWMS Data API version", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/ClobController.java b/cwms-data-api/src/main/java/cwms/cda/api/ClobController.java index 802d6589e..b3da19295 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/ClobController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/ClobController.java @@ -35,16 +35,16 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.http.HttpCode; +import io.javalin.http.HttpStatus; import io.javalin.http.HttpResponseException; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.Objects; import java.util.Optional; @@ -112,7 +112,8 @@ protected DSLContext getDslContext(Context ctx) { @OpenApiContent(type = Formats.XMLV2, from = Clobs.class) }) }, - tags = {TAG} + tags = {TAG}, + path = "/clobs" ) @Override public void getAll(@NotNull Context ctx) { @@ -129,7 +130,7 @@ public void getAll(@NotNull Context ctx) { if (!CwmsDTOPaginated.CURSOR_CHECK.invoke(cursor)) { ctx.json(new CdaError("cursor or page passed in but failed validation")) - .status(HttpCode.BAD_REQUEST); + .status(HttpStatus.BAD_REQUEST); return; } @@ -151,7 +152,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException e) { CdaError re = new CdaError("Failed to process request to retrieve "); logger.atSevere().withCause(e).log("Failed to process request to retrieve Basin"); @@ -191,7 +192,8 @@ public void getAll(@NotNull Context ctx) { @OpenApiContent(type = TEXT_PLAIN), }) }, - tags = {TAG} + tags = {TAG}, + path = "/clobs/{" + CLOB_ID + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String clobId) { @@ -237,7 +239,7 @@ public void getOne(@NotNull Context ctx, @NotNull String clobId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { ctx.status(HttpServletResponse.SC_NOT_FOUND).json(new CdaError("Unable to find " + "clob based on given parameters")); @@ -262,20 +264,21 @@ public void getOne(@NotNull Context ctx, @NotNull String clobId) { @OpenApiParam(name = FAIL_IF_EXISTS, type = Boolean.class, description = "Create will fail if provided ID already exists. Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/clobs" ) @Override public void create(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); ContentType contentType = Formats.parseHeader(formatHeader, Clob.class); - Clob clob = Formats.parseContent(contentType, ctx.bodyAsInputStream(), Clob.class); + Clob clob = Formats.parseContent(contentType, ctx.bodyInputStream(), Clob.class); ClobDao dao = new ClobDao(dsl); dao.create(clob, failIfExists); - ctx.status(HttpCode.CREATED); + ctx.status(HttpStatus.CREATED); } } @@ -303,8 +306,9 @@ public void create(@NotNull Context ctx) { }, required = true), description = "Update clob", - method = HttpMethod.PATCH, - tags = {TAG} + methods = HttpMethod.PATCH, + tags = {TAG}, + path = "/clobs/{" + CLOB_ID + "}" ) @Override public void update(@NotNull Context ctx, @NotNull String clobId) { @@ -318,20 +322,20 @@ public void update(@NotNull Context ctx, @NotNull String clobId) { } DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ClobDao dao = new ClobDao(dsl); ContentType contentType = Formats.parseHeader(formatHeader, Clob.class); - Clob clob = Formats.parseContent(contentType, ctx.bodyAsInputStream(), Clob.class); + Clob clob = Formats.parseContent(contentType, ctx.bodyInputStream(), Clob.class); if (clob.getOfficeId() == null) { - throw new HttpResponseException(HttpCode.BAD_REQUEST.getStatus(), + throw new HttpResponseException(HttpStatus.BAD_REQUEST.getCode(), "An office is required in the request body when updating a clob"); } clob = fillOutClob(clob, clobId); if (!Objects.equals(clob.getId(), clobId)) { - throw new HttpResponseException(HttpCode.BAD_REQUEST.getStatus(), + throw new HttpResponseException(HttpStatus.BAD_REQUEST.getCode(), "Clob id in body does not match id in path"); } @@ -376,8 +380,9 @@ private Clob fillOutClob(Clob clob, String reqId) { + "Client libraries should detect slashes and choose the appropriate field. \"ignored\" is suggested for the path endpoint."), }, description = "Delete clob", - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/clobs/{" + CLOB_ID + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String clobId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java b/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java index 02fbbcc58..da00f4764 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/Controllers.java @@ -29,15 +29,12 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; -import cwms.cda.api.enums.UnitSystem; -import cwms.cda.api.enums.VersionType; import cwms.cda.api.errors.RequiredQueryParameterException; import cwms.cda.data.dao.JooqDao; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import cwms.cda.helpers.DateUtils; -import io.javalin.core.validation.JavalinValidation; -import io.javalin.core.validation.Validator; +import io.javalin.validation.Validator; import io.javalin.http.Context; import java.time.Instant; import java.time.ZonedDateTime; @@ -256,12 +253,12 @@ public final class Controllers { public static final String QUERY = "query"; public static final String INCLUDE_ROLES = "include-roles"; - - static { - JavalinValidation.register(JooqDao.DeleteMethod.class, Controllers::getDeleteMethod); - JavalinValidation.register(VersionType.class, VersionType::versionTypeFor); - JavalinValidation.register(UnitSystem.class, UnitSystem::systemFor); - } + // TODO: moved to config block + // static { + // JavalinValidation.register(JooqDao.DeleteMethod.class, Controllers::getDeleteMethod); + // JavalinValidation.register(VersionType.class, VersionType::versionTypeFor); + // JavalinValidation.register(UnitSystem.class, UnitSystem::systemFor); + // } private Controllers() { @@ -509,9 +506,9 @@ public static Instant requiredInstant(Context ctx, String param) { public static void addDeprecatedContentTypeWarning(Context ctx, ContentType type) { if (type.getType().equalsIgnoreCase(Formats.TAB)) { - ctx.res.addHeader(DEPRECATED_HEADER, DEPRECATED_TAB); + ctx.addHeader(DEPRECATED_HEADER, DEPRECATED_TAB); } else if (type.getType().equalsIgnoreCase(Formats.CSV)) { - ctx.res.addHeader(DEPRECATED_HEADER, DEPRECATED_CSV); + ctx.addHeader(DEPRECATED_HEADER, DEPRECATED_CSV); } } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/CountyController.java b/cwms-data-api/src/main/java/cwms/cda/api/CountyController.java index a1507c0ff..c0de000da 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/CountyController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/CountyController.java @@ -41,11 +41,11 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -82,11 +82,11 @@ private Timer.Context markAndTime(String subject) { @OpenApiResponse(status = "" + HttpServletResponse.SC_OK, description = "A list of counties.", content = { - @OpenApiContent(from = County.class, isArray = true, - type = Formats.JSONV2), + @OpenApiContent(from = County[].class, type = Formats.JSONV2), }), }, - tags = {"Counties"} + tags = {"Counties"}, + path = "/counties" ) @Override public void getAll(@NotNull Context ctx) { @@ -103,7 +103,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve counties", ex); @@ -112,25 +112,25 @@ public void getAll(@NotNull Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(Context ctx, @NotNull String county) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(Context ctx, @NotNull String county) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(Context ctx, @NotNull String county) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/DownstreamLocationsGetController.java b/cwms-data-api/src/main/java/cwms/cda/api/DownstreamLocationsGetController.java index 1fce4d6a7..609c84b41 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/DownstreamLocationsGetController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/DownstreamLocationsGetController.java @@ -48,13 +48,13 @@ import cwms.cda.data.dto.stream.StreamLocation; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -89,10 +89,11 @@ private Timer.Context markAndTime(String subject) { @OpenApiParam(name = AREA_UNIT, description = "Area units."), }, responses = { - @OpenApiResponse(status = STATUS_200, content = {@OpenApiContent(isArray = true, type = Formats.JSONV1, from = StreamLocation.class)}) + @OpenApiResponse(status = STATUS_200, content = {@OpenApiContent(type = Formats.JSONV1, from = StreamLocation[].class)}) }, description = "Returns matching downstream stream locations.", - tags = {StreamLocationController.TAG} + tags = {StreamLocationController.TAG}, + path = "/stream/location/downstream" ) public void handle(@NotNull Context ctx) throws Exception { String locationId = ctx.pathParam(NAME); @@ -117,7 +118,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve downstream locations", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/EmbankmentController.java b/cwms-data-api/src/main/java/cwms/cda/api/EmbankmentController.java index 65a1f9894..5d25b4c5d 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/EmbankmentController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/EmbankmentController.java @@ -56,14 +56,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -99,12 +99,13 @@ private Timer.Context markAndTime(String subject) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = Embankment.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = Embankment.class) + @OpenApiContent(type = Formats.JSONV1, from = Embankment[].class), + @OpenApiContent(type = Formats.JSON, from = Embankment[].class) }) }, description = "Returns matching CWMS Embankment Data for a Reservoir Project.", - tags = {TAG} + tags = {TAG}, + path = "/embankment" ) @Override public void getAll(Context ctx) { @@ -123,7 +124,7 @@ public void getAll(Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Embankments", ex); @@ -144,12 +145,13 @@ public void getAll(Context ctx) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = Embankment.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = Embankment.class) + @OpenApiContent(type = Formats.JSONV1, from = Embankment[].class), + @OpenApiContent(type = Formats.JSON, from = Embankment[].class) }) }, description = "Returns CWMS Embankment Data", - tags = {TAG} + tags = {TAG}, + path = "/embankment/{" + NAME + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String name) { @@ -168,7 +170,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Embankment", ex); @@ -188,8 +190,9 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { description = "Create will fail if provided ID already exists. Default: true") }, description = "Create CWMS Embankment", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAG}, + path = "/embankment", responses = { @OpenApiResponse(status = STATUS_204, description = "Embankment successfully stored to CWMS.") } @@ -197,7 +200,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @Override public void create(Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Embankment.class); Embankment embankment = Formats.parseContent(contentType, ctx.body(), Embankment.class); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); @@ -208,7 +211,6 @@ public void create(Context ctx) { "Embankment successfully stored to CWMS", embankment.getLocation().getName()); ctx.status(HttpServletResponse.SC_CREATED).json(re); } - } @OpenApi( @@ -222,8 +224,9 @@ public void create(Context ctx) { @OpenApiParam(name = NAME, required = true, description = "Specifies the new embankment name. ") }, description = "Rename CWMS Embankment", - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, tags = {TAG}, + path = "/embankment/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_204, description = "Embankment successfully renamed in CWMS.") } @@ -254,8 +257,9 @@ public void update(@NotNull Context ctx, @NotNull String name) { type = JooqDao.DeleteMethod.class) }, description = "Delete CWMS Embankment", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, tags = {TAG}, + path = "/embankment/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Embankment successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " @@ -275,4 +279,4 @@ public void delete(@NotNull Context ctx, @NotNull String name) { ctx.status(HttpServletResponse.SC_OK).json(re); } } -} \ No newline at end of file +} diff --git a/cwms-data-api/src/main/java/cwms/cda/api/EntityController.java b/cwms-data-api/src/main/java/cwms/cda/api/EntityController.java index 549d7a76b..ee1661f07 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/EntityController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/EntityController.java @@ -33,14 +33,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -81,10 +81,11 @@ private Timer.Context markAndTime(String subject) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, from = Entity.class, type = Formats.JSONV1) + @OpenApiContent(from = Entity[].class, type = Formats.JSONV1) }) }, - tags = {TAG} + tags = {TAG}, + path = "/entity" ) @Override @@ -119,7 +120,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Entities", ex); @@ -143,7 +144,8 @@ public void getAll(@NotNull Context ctx) { @OpenApiContent(from = Entity.class, type = Formats.JSONV1) }) }, - tags = {TAG} + tags = {TAG}, + path = "/entity/{" + ENTITY_ID + "}" ) @Override @@ -168,7 +170,7 @@ public void getOne(@NotNull Context ctx, @NotNull String entityId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Entity", ex); @@ -187,8 +189,9 @@ public void getOne(@NotNull Context ctx, @NotNull String entityId) { responses = { @OpenApiResponse(status = STATUS_201, description = "Entity successfully stored to CWMS") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/entity" ) @Override @@ -196,7 +199,7 @@ public void create(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Entity.class); Entity entity = Formats.parseContent(contentType, ctx.body(), Entity.class); EntityDao dao = new EntityDao(dsl); @@ -215,8 +218,9 @@ public void create(@NotNull Context ctx) { @OpenApiParam(name = ENTITY_ID, required = true, description = "Specifies the entity ID of the " + " Entity to be updated. (e.g., NWS)") }, - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, tags = {TAG}, + path = "/entity/{" + ENTITY_ID + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Entity updated successfully in CWMS"), } @@ -226,9 +230,9 @@ public void create(@NotNull Context ctx) { public void update(@NotNull Context ctx, @NotNull String entityId) { try (final Timer.Context ignored = markAndTime(UPDATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Entity.class); - Entity entity = Formats.parseContent(contentType, ctx.bodyAsInputStream(), Entity.class); + Entity entity = Formats.parseContent(contentType, ctx.bodyInputStream(), Entity.class); // Validate the office ID and entity ID are provided. entity.validate(); @@ -261,7 +265,8 @@ public void update(@NotNull Context ctx, @NotNull String entityId) { @OpenApiResponse(status = STATUS_204, description = "Entity deleted successfully"), @OpenApiResponse(status = STATUS_404, description = "Entity not found for the given parameters."), }, - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, + path = "/entity/{" + ENTITY_ID + "}", tags = {TAG} ) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LevelRefsController.java b/cwms-data-api/src/main/java/cwms/cda/api/LevelRefsController.java index 131ce1707..1c36d4e2d 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LevelRefsController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LevelRefsController.java @@ -53,13 +53,13 @@ import cwms.cda.data.dto.locationlevel.LocationLevelRefs; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.time.Instant; import javax.servlet.http.HttpServletResponse; @@ -119,7 +119,8 @@ public LevelRefsController(MetricRegistry metrics) { @OpenApiContent(from = LocationLevelRefs.class, type = Formats.JSON), }) }, - tags = LevelsController.TAG) + tags = LevelsController.TAG, + path = "/levels/ref") @Override public void handle(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime(metrics, getClass().getName(), GET_ALL)) { @@ -149,7 +150,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve location level refs", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LevelsAsTimeSeriesController.java b/cwms-data-api/src/main/java/cwms/cda/api/LevelsAsTimeSeriesController.java index 8aced63a5..df29c04ff 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LevelsAsTimeSeriesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LevelsAsTimeSeriesController.java @@ -47,12 +47,12 @@ import cwms.cda.formatters.Formats; import cwms.cda.helpers.DateUtils; import hec.data.level.JDomLocationLevelRef; -import io.javalin.core.validation.Validator; +import io.javalin.validation.Validator; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.time.ZoneId; import java.time.ZonedDateTime; import javax.servlet.http.HttpServletResponse; @@ -115,7 +115,8 @@ public LevelsAsTimeSeriesController(MetricRegistry metrics) { + "implemented") }, description = "Retrieves requested Location Level", - tags = LevelsController.TAG + tags = LevelsController.TAG, + path = "/levels/as-ts" ) public void handle(Context ctx) { logUnusedPathParameter(ctx, LEVEL_ID, "Body contains required information"); @@ -149,6 +150,5 @@ public void handle(Context ctx) { ctx.json(timeSeries); ctx.status(HttpServletResponse.SC_OK); } - } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LevelsController.java b/cwms-data-api/src/main/java/cwms/cda/api/LevelsController.java index 557dbb4bd..8300dc934 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LevelsController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LevelsController.java @@ -59,23 +59,22 @@ import cwms.cda.helpers.DateUtils; import cwms.cda.helpers.annotations.IgnoreRequiredQueryParamMismatch; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.BadRequestResponse; import io.javalin.http.Context; -import io.javalin.http.HttpCode; +import io.javalin.http.HttpStatus; import io.javalin.http.HttpResponseException; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.time.Instant; import java.time.ZoneId; -import java.time.temporal.ChronoUnit; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -113,7 +112,7 @@ private Timer.Context markAndTime(String subject) { @OpenApiContent(from = LocationLevel.class, type = Formats.JSON), }, required = true), - method = HttpMethod.POST, + methods = HttpMethod.POST, path = "/levels", tags = TAG ) @@ -142,10 +141,10 @@ public void create(@NotNull Context ctx) { } private LocationLevel deserializeLocationLevel(Context ctx) throws IOException { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, LocationLevel.class); StringWriter writer = new StringWriter(); - IOUtils.copy(ctx.bodyAsInputStream(), writer, StandardCharsets.UTF_8); + IOUtils.copy(ctx.bodyInputStream(), writer, StandardCharsets.UTF_8); String body = writer.toString(); if (body.contains("constituent")) { return Formats.parseContent(contentType, body, VirtualLocationLevel.class); @@ -184,8 +183,8 @@ private LocationLevel deserializeLocationLevel(Context ctx) throws IOException { + "specified).If this field is not specified, the default time zone of UTC " + "shall be used."), }, - method = HttpMethod.DELETE, - path = "/levels", + methods = HttpMethod.DELETE, + path = "/levels/{" + LEVEL_ID + "}", tags = TAG) @Override public void delete(@NotNull Context ctx, @NotNull String levelId) { @@ -276,7 +275,8 @@ public void delete(@NotNull Context ctx, @NotNull String levelId) { @OpenApiContent(from = LocationLevels.class, type = Formats.JSONV2), }) }, - tags = TAG) + tags = TAG, + path = "/levels") @Override public void getAll(@NotNull Context ctx) { @@ -333,7 +333,7 @@ public void getAll(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_OK); byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { //Use the type string, not the full string with properties. //i.e. application/json not application/json;version=1 @@ -350,7 +350,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } addDeprecatedContentTypeWarning(ctx, contentType); } catch (IOException ex) { @@ -404,7 +404,8 @@ public void getAll(@NotNull Context ctx) { }) }, description = "Retrieves requested Location Level", - tags = TAG + tags = TAG, + path = "/levels/{" + LEVEL_ID + "}" ) @IgnoreRequiredQueryParamMismatch(parameterNames = {EFFECTIVE_DATE}) @Override @@ -438,7 +439,7 @@ String.class, null, metrics, name(LevelsController.class.getName(), byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError re = new CdaError(ERROR_MSG); LOGGER.atSevere().withCause(ex).log(ERROR_MSG); @@ -464,8 +465,8 @@ String.class, null, metrics, name(LevelsController.class.getName(), }, required = true), description = "Update CWMS Location Level", - method = HttpMethod.PATCH, - path = "/levels", + methods = HttpMethod.PATCH, + path = "/levels/{" + LEVEL_ID + "}", tags = TAG ) @Override @@ -473,12 +474,12 @@ public void update(@NotNull Context ctx, @NotNull String oldLevelId) { try (final Timer.Context ignored = markAndTime(UPDATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, LocationLevel.class); LocationLevel levelFromBody = deserializeLocationLevel(ctx); String officeId = levelFromBody.getOfficeId(); if (officeId == null) { - throw new HttpResponseException(HttpCode.BAD_REQUEST.getStatus(), + throw new HttpResponseException(HttpStatus.BAD_REQUEST.getCode(), "The request body must specify the office."); } String newLevelId = levelFromBody.getLocationLevelId(); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LocationCategoryController.java b/cwms-data-api/src/main/java/cwms/cda/api/LocationCategoryController.java index 479da80c8..848f247ba 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LocationCategoryController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LocationCategoryController.java @@ -48,14 +48,15 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import java.util.List; import java.util.Optional; @@ -89,13 +90,13 @@ private Timer.Context markAndTime(String subject) { + "all offices shall be returned."),}, responses = {@OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, from = LocationCategory.class, type = - Formats.JSON) + @OpenApiContent(from = LocationCategory[].class, type = Formats.JSON) }) }, description = "Returns CWMS Location Category Data", - tags = {TAG} + tags = {TAG}, + path = "/locations/category" ) @Override public void getAll(Context ctx) { @@ -120,7 +121,7 @@ public void getAll(Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { CdaError re = new CdaError("Cannot find requested location category for " + "office provided: " + office); @@ -154,7 +155,8 @@ public void getAll(Context ctx) { ) }, description = "Retrieves requested Location Category", - tags = {TAG}) + tags = {TAG}, + path = "/locations/category/{" + CATEGORY_ID + "}") @Override public void getOne(Context ctx, @NotNull String categoryId) { @@ -178,7 +180,7 @@ public void getOne(Context ctx, @NotNull String categoryId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { CdaError re = new CdaError("Cannot find requested location category id: " + categoryId + " with office: " + office); @@ -200,15 +202,16 @@ public void getOne(Context ctx, @NotNull String categoryId) { @OpenApiContent(from = LocationCategory.class, type = Formats.JSON) }, required = true), - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/locations/category" ) @Override public void create(Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(formatHeader, LocationCategory.class); LocationCategory deserialize = Formats.parseContent(contentType, body, LocationCategory.class); @@ -218,7 +221,7 @@ public void create(Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(Context ctx, @NotNull String categoryId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -235,8 +238,9 @@ public void update(Context ctx, @NotNull String categoryId) { @OpenApiParam(name = CASCADE_DELETE, type = Boolean.class, description = "Specifies whether to delete any location groups in this location category. Default: false"), }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/locations/category/{" + CATEGORY_ID + "}" ) @Override public void delete(Context ctx, @NotNull String categoryId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LocationController.java b/cwms-data-api/src/main/java/cwms/cda/api/LocationController.java index 9c23e178f..6c60e692f 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LocationController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LocationController.java @@ -73,14 +73,15 @@ import cwms.cda.formatters.UnsupportedFormatException; import cwms.cda.helpers.ZoneIdHelper; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.config.Key; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.sql.SQLException; import java.util.List; @@ -154,7 +155,7 @@ private Timer.Context markAndTime(String subject) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV2, from = Location.class), + @OpenApiContent(type = Formats.JSONV2, from = Location[].class), @OpenApiContent(type = Formats.JSON), @OpenApiContent(type = Formats.TAB), @OpenApiContent(type = Formats.CSV), @@ -167,7 +168,8 @@ private Timer.Context markAndTime(String subject) { }, description = "Returns CWMS Location Data. The Catalog end-point is also capable of " + "retrieving lists of locations and can filter on additional fields.", - tags = {LOCATIONS_TAG} + tags = {LOCATIONS_TAG}, + path = "/locations" ) @Override public void getAll(@NotNull Context ctx) { @@ -195,14 +197,14 @@ public void getAll(@NotNull Context ctx) { office); ctx.contentType(contentType.toString()); - ObjectMapper mapper = ctx.appAttribute("ObjectMapper"); + ObjectMapper mapper = ctx.appData(new Key("ObjectMapper")); // TODO: Constant String result = mapper.writeValueAsString(collection); requestResultSize.update(result.length()); ctx.status(HttpServletResponse.SC_OK); byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else if (formatParm.isEmpty() && !isLegacyFormat) { List locations = locationsDao.getLocations(names, units, datum, office); results = Formats.format(contentType, locations, Location.class); @@ -212,7 +214,7 @@ public void getAll(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_OK); byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { String format = Formats.getLegacyTypeFromContentType(contentType); results = locationsDao.getLocations(names, format, units, datum, office); @@ -227,7 +229,7 @@ public void getAll(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_OK); byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } addDeprecatedContentTypeWarning(ctx, contentType); @@ -268,7 +270,8 @@ public void getAll(@NotNull Context ctx) { + "inputs provided the location was not found.") }, description = "Returns CWMS Location Data", - tags = {LOCATIONS_TAG} + tags = {LOCATIONS_TAG}, + path = "/locations/{" + LOCATION_ID + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String locationId) { @@ -294,7 +297,7 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { ctx.status(HttpServletResponse.SC_OK); byte[] bytes = serializedLocation.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); addDeprecatedContentTypeWarning(ctx, contentType); } catch (IOException ex) { @@ -320,7 +323,7 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { + "be updated with the new values.") }, description = "Create new CWMS Location", - method = HttpMethod.POST, + methods = HttpMethod.POST, path = "/locations", tags = {LOCATIONS_TAG} ) @@ -332,7 +335,7 @@ public void create(@NotNull Context ctx) { LocationsDao locationsDao = getLocationsDao(dsl); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Location.class); Location locationFromBody = Formats.parseContent(contentType, ctx.body(), Location.class); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); @@ -358,7 +361,7 @@ public void create(@NotNull Context ctx) { }, required = true), description = "Update CWMS Location", - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, path = "/locations", tags = {LOCATIONS_TAG}, responses = { @@ -374,7 +377,7 @@ public void update(@NotNull Context ctx, @NotNull String locationId) { LocationsDao locationsDao = getLocationsDao(dsl); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Location.class); Location locationFromBody = Formats.parseContent(contentType, ctx.body(), Location.class); //getLocation will throw an error if location does not exist @@ -400,7 +403,6 @@ public void update(@NotNull Context ctx, @NotNull String locationId) { logger.atSevere().withCause(ex).log("%s", re.toString()); ctx.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).json(re); } - } @OpenApi( @@ -416,8 +418,8 @@ public void update(@NotNull Context ctx, @NotNull String locationId) { + " associated data for this location before deleting the location itself. Default: false") }, description = "Delete CWMS Location", - method = HttpMethod.DELETE, - path = "/locations", + methods = HttpMethod.DELETE, + path = "/locations/{" + LOCATION_ID + "}", tags = {LOCATIONS_TAG}, responses = { @OpenApiResponse(status = STATUS_200, description = "Location successfully deleted from CWMS."), diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java index bd9756086..9280806ca 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LocationGroupController.java @@ -106,7 +106,7 @@ private Timer.Context markAndTime(String subject) { }) }, description = "Returns CWMS Location Groups Data", tags = {TAG}, - path = "/" + path = "/location/group" ) @Override public void getAll(@NotNull Context ctx) { @@ -185,7 +185,7 @@ Boolean.class, false, metrics, name(LocationGroupController.class.getName(), + Formats.GEOJSON + "." + "For more information about accept header usage, see this page.", tags = {TAG}, - path = "/" + path = "/location/group/{" + GROUP_ID + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String groupId) { @@ -255,7 +255,7 @@ public void getOne(@NotNull Context ctx, @NotNull String groupId) { }, methods = {HttpMethod.POST}, tags = {TAG}, - path = "/" + path = "/location/group" ) @Override public void create(@NotNull Context ctx) { @@ -324,7 +324,7 @@ public void create(@NotNull Context ctx) { }, methods = {HttpMethod.PATCH}, tags = {TAG}, - path = "/" + path = "/locatiton/group/{" + GROUP_ID + "}" ) @Override public void update(@NotNull Context ctx, @NotNull String groupId) { @@ -378,7 +378,7 @@ public void update(@NotNull Context ctx, @NotNull String groupId) { }, methods = HttpMethod.DELETE, tags = {TAG}, - path = "/{location-id}" + path = "/location/group/{location-id}" ) @Override public void delete(@NotNull Context ctx, @NotNull String groupId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LocationKindController.java b/cwms-data-api/src/main/java/cwms/cda/api/LocationKindController.java index 680aea432..63efc0a07 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LocationKindController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LocationKindController.java @@ -45,14 +45,16 @@ import cwms.cda.data.dto.CwmsIdLocationKind; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -88,12 +90,12 @@ public LocationKindController(MetricRegistry metrics) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = CwmsIdLocationKind.class), + @OpenApiContent(type = Formats.JSONV1, from = CwmsIdLocationKind[].class), }) }, description = "Returns CWMS Location Data. The Catalog end-point is also capable of " + "retrieving lists of locations and can filter on additional fields.", - method = HttpMethod.GET, + methods = HttpMethod.GET, path = "/locations/with-kind", tags = {TAG} ) @@ -122,7 +124,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Location Kind", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/LookupTypeController.java b/cwms-data-api/src/main/java/cwms/cda/api/LookupTypeController.java index 15c5c25ad..6408c5f85 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/LookupTypeController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/LookupTypeController.java @@ -48,14 +48,14 @@ import cwms.cda.data.dto.StatusResponse; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -79,11 +79,12 @@ public LookupTypeController(MetricRegistry metrics) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSON, from = LookupType.class) + @OpenApiContent(type = Formats.JSON, from = LookupType[].class) }) }, description = "Returns matching CWMS Lookup Type Data.", - tags = {TAG} + tags = {TAG}, + path = "/lookup-type" ) @Override public void getAll(Context ctx) { @@ -103,7 +104,7 @@ public void getAll(Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Lookup Types", ex); @@ -112,7 +113,7 @@ public void getAll(Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context context, @NotNull String s) { context.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -129,8 +130,9 @@ public void getOne(@NotNull Context context, @NotNull String s) { }, required = true), description = "Create CWMS Lookup Type", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAG}, + path = "/lookup-type", responses = { @OpenApiResponse(status = STATUS_204, description = "Lookup Type successfully stored to CWMS.") } @@ -140,7 +142,7 @@ public void create(Context ctx) { String category = requiredParam(ctx, CATEGORY); String prefix = requiredParam(ctx, PREFIX); try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, LookupType.class); LookupType lookupType = Formats.parseContent(contentType, ctx.body(), LookupType.class); DSLContext dsl = getDslContext(ctx); @@ -166,8 +168,9 @@ public void create(Context ctx) { }, required = true), description = "Update CWMS Lookup Type", - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, tags = {TAG}, + path = "/lookup-type/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Updated Lookup Type") } @@ -178,7 +181,7 @@ public void update(Context ctx, String name) { String category = requiredParam(ctx, CATEGORY); String prefix = requiredParam(ctx, PREFIX); try (Timer.Context ignored = markAndTime(UPDATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, LookupType.class); LookupType lookupType = Formats.parseContent(contentType, ctx.body(), LookupType.class); DSLContext dsl = getDslContext(ctx); @@ -200,8 +203,9 @@ public void update(Context ctx, String name) { @OpenApiParam(name = OFFICE, required = true, description = "Specifies the owning office of the lookup type to be deleted."), }, description = "Delete CWMS Lookup Type", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, tags = {TAG}, + path = "/lookup-type/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Lookup Type successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of inputs provided the lookup type was not found.") diff --git a/cwms-data-api/src/main/java/cwms/cda/api/MeasurementController.java b/cwms-data-api/src/main/java/cwms/cda/api/MeasurementController.java index b5d8116dc..f27a38aeb 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/MeasurementController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/MeasurementController.java @@ -49,7 +49,6 @@ import static cwms.cda.api.Controllers.TIMEZONE; import static cwms.cda.api.Controllers.TIME_FORMAT_DESC; import static cwms.cda.api.Controllers.UNIT_SYSTEM; -import static cwms.cda.api.Controllers.queryParamAsClass; import static cwms.cda.api.Controllers.queryParamAsDouble; import static cwms.cda.api.Controllers.queryParamAsInstant; import static cwms.cda.api.Controllers.requiredParam; @@ -69,14 +68,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.time.Instant; import java.util.List; @@ -132,13 +131,14 @@ private Timer.Context markAndTime(String subject) { }, responses = { @OpenApiResponse(status = "200", content = { - @OpenApiContent(isArray = true, type = Formats.JSONV2, from = Measurement.class), - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = MeasurementLegacy.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = MeasurementLegacy.class) + @OpenApiContent(type = Formats.JSONV2, from = Measurement[].class), + @OpenApiContent(type = Formats.JSONV1, from = MeasurementLegacy[].class), + @OpenApiContent(type = Formats.JSON, from = MeasurementLegacy[].class) }) }, description = "Returns matching measurement data.", - tags = {TAG} + tags = {TAG}, + path = "/measurement" ) @Override public void getAll(@NotNull Context ctx) { @@ -170,7 +170,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Measurements", ex); @@ -179,7 +179,7 @@ public void getAll(@NotNull Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String locationId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -188,9 +188,9 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { @OpenApi( requestBody = @OpenApiRequestBody( content = { - @OpenApiContent(isArray = true, from = Measurement.class, type = Formats.JSONV2), - @OpenApiContent(isArray = true, from = MeasurementLegacy.class, type = Formats.JSONV1), - @OpenApiContent(isArray = true, from = MeasurementLegacy.class, type = Formats.JSON) + @OpenApiContent(from = Measurement[].class, type = Formats.JSONV2), + @OpenApiContent(from = MeasurementLegacy[].class, type = Formats.JSONV1), + @OpenApiContent(from = MeasurementLegacy[].class, type = Formats.JSON) }, required = true), queryParams = { @@ -198,8 +198,9 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { description = "Create will fail if provided Measurement(s) already exist. Default: true") }, description = "Create new measurement(s).", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAG}, + path = "/measurements", responses = { @OpenApiResponse(status = "201", description = "Measurement(s) successfully stored.") } @@ -208,7 +209,7 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { public void create(Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Measurement.class); List measurements = Formats.parseContentList(contentType, ctx.body(), Measurement.class); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); @@ -220,7 +221,7 @@ public void create(Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context ctx, @NotNull String locationId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -245,8 +246,9 @@ public void update(@NotNull Context ctx, @NotNull String locationId) { @OpenApiParam(name = MAX_NUMBER, type = Integer.class, description = "Specifies the max number-id of the measurement to delete. Only applies to integer measurement IDs."), }, description = "Delete an existing measurement.", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, tags = {TAG}, + path = "/measurements/{" + LOCATION_ID + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Measurement successfully deleted."), @OpenApiResponse(status = STATUS_404, description = "Measurement not found.") diff --git a/cwms-data-api/src/main/java/cwms/cda/api/MeasurementTimeExtentsGetController.java b/cwms-data-api/src/main/java/cwms/cda/api/MeasurementTimeExtentsGetController.java index 243bc8498..c47a0d30c 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/MeasurementTimeExtentsGetController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/MeasurementTimeExtentsGetController.java @@ -41,13 +41,13 @@ import cwms.cda.data.dto.CwmsIdTimeExtentsEntry; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -75,11 +75,12 @@ private Timer.Context markAndTime() { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = CwmsIdTimeExtentsEntry.class) + @OpenApiContent(type = Formats.JSONV1, from = CwmsIdTimeExtentsEntry[].class) }) }, description = "Returns matching downstream stream locations.", - tags = {MeasurementController.TAG} + tags = {MeasurementController.TAG}, + path = "/measurements/extents" ) public void handle(@NotNull Context ctx) throws Exception { String officeIdMask = ctx.queryParam(OFFICE_MASK); @@ -97,7 +98,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve downstream locations", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/OfficeController.java b/cwms-data-api/src/main/java/cwms/cda/api/OfficeController.java index 7d02e7beb..f6e24c6c4 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/OfficeController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/OfficeController.java @@ -21,12 +21,12 @@ import cwms.cda.formatters.Formats; import cwms.cda.formatters.OfficeFormatV1; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.Serializable; import java.util.HashMap; import java.util.List; @@ -83,11 +83,11 @@ private Timer.Context markAndTime(String subject) { @OpenApiResponse(status = STATUS_200, description = "A list of offices.", content = { - @OpenApiContent(from = Office.class, isArray = true, type = Formats.JSON), - @OpenApiContent(from = OfficeFormatV1.class, isArray = true, type = Formats.JSONV1), - @OpenApiContent(from = Office.class, isArray = true, type = Formats.JSONV2), + @OpenApiContent(from = Office[].class, type = Formats.JSON), + @OpenApiContent(from = OfficeFormatV1[].class, type = Formats.JSONV1), + @OpenApiContent(from = Office[].class, type = Formats.JSONV2), }), - }, tags = { "Offices" } + }, tags = { "Offices" }, path = "/offices" ) @Override public void getAll(Context ctx) { @@ -141,7 +141,8 @@ public void getAll(Context ctx) { @OpenApiContent(from = OfficeFormatV1.class, type = Formats.XMLV1), @OpenApiContent(from = Office.class, type = Formats.XMLV2) }) - }, tags = { "Offices" }) + }, tags = { "Offices" } + , path = "/office/{office}") @Override public void getOne(Context ctx, String officeId) { try (final Timer.Context timeContext = markAndTime(GET_ONE)) { @@ -167,22 +168,21 @@ public void getOne(Context ctx, String officeId) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(Context ctx, String officeId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(Context ctx, String officeId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/ParametersController.java b/cwms-data-api/src/main/java/cwms/cda/api/ParametersController.java index da71d759b..7778dfd48 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/ParametersController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/ParametersController.java @@ -22,12 +22,12 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -51,17 +51,16 @@ private Timer.Context markAndTime(String subject) { return Controllers.markAndTime(metrics, getClass().getName(), subject); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(@NotNull Context ctx, @NotNull String id) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); - } @OpenApi( @@ -81,11 +80,12 @@ public void delete(@NotNull Context ctx, @NotNull String id) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, from = Parameter.class, type = Formats.JSONV2), - @OpenApiContent(isArray = true, from = Parameter.class, type = Formats.JSON) + @OpenApiContent(from = Parameter[].class, type = Formats.JSONV2), + @OpenApiContent(from = Parameter[].class, type = Formats.JSON) }), }, - tags = {"Parameters"} + tags = {"Parameters"}, + path = "/paramters" ) @Override public void getAll(@NotNull Context ctx) { @@ -125,7 +125,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError re = new CdaError("Error writing response"); LOGGER.atSevere().withCause(ex).log("Failed to process request to retrieve Basins"); @@ -133,16 +133,15 @@ public void getAll(@NotNull Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String id) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context ctx, @NotNull String id) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/PoolController.java b/cwms-data-api/src/main/java/cwms/cda/api/PoolController.java index a7e8e8cd7..4a6319100 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/PoolController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/PoolController.java @@ -12,7 +12,6 @@ import com.google.common.flogger.FluentLogger; import cwms.cda.api.errors.CdaError; import cwms.cda.api.errors.ExceptionTraceSupport; -import cwms.cda.data.dao.JooqDao; import cwms.cda.data.dao.PoolDao; import cwms.cda.data.dto.Pool; import cwms.cda.data.dto.Pools; @@ -20,14 +19,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -91,7 +90,7 @@ private Timer.Context markAndTime(String subject) { @OpenApiResponse(status = STATUS_501, description = "request format is not" + " implemented")}, description = "Returns Pools Data", - tags = {TAG}) + tags = {TAG}, path = "/pool") @Override public void getAll(@NotNull Context ctx) { try (final Timer.Context timeContext = markAndTime(GET_ALL)) { @@ -138,7 +137,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Pools", ex); @@ -179,7 +178,8 @@ public void getAll(@NotNull Context ctx) { + "inputs provided the Location Category was not found."), @OpenApiResponse(status = STATUS_501, description = "request format is not " + "implemented")}, - description = "Retrieves requested Pool", tags = {TAG}) + description = "Retrieves requested Pool", tags = {TAG}, + path = "/pool/{" + POOL_ID + "}") @Override public void getOne(@NotNull Context ctx, @NotNull String poolId) { try (final Timer.Context timeContext = markAndTime(GET_ONE)) { @@ -224,7 +224,7 @@ public void getOne(@NotNull Context ctx, @NotNull String poolId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, @@ -247,8 +247,9 @@ public void getOne(@NotNull Context ctx, @NotNull String poolId) { description = "Create will create the pool name if it doesn't already exists. Default: true") }, description = "Create CWMS Pool", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAG}, + path = "/pool", responses = { @OpenApiResponse(status = STATUS_204, description = "Pool successfully stored to CWMS.") } @@ -261,7 +262,7 @@ public void create(@NotNull Context ctx) { .getOrDefault(true); boolean createPoolName = ctx.queryParamAsClass(CREATE_POOL_NAME, Boolean.class) .getOrDefault(true); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Pool.class); Pool pool = Formats.parseContent(contentType, ctx.body(), Pool.class); PoolDao dao = new PoolDao(dsl); @@ -284,8 +285,9 @@ public void create(@NotNull Context ctx) { @OpenApiParam(name = NAME, required = true, description = "Specifies the new pool name. ") }, description = "Rename CWMS Pool", - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, tags = {TAG}, + path = "/pool/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_204, description = "Pool successfully renamed in CWMS.") } @@ -315,8 +317,9 @@ public void update(@NotNull Context ctx, @NotNull String poolId) { + "the pool to be deleted.") }, description = "Delete CWMS Pool", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, tags = {TAG}, + path = "/pool/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Pool successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " diff --git a/cwms-data-api/src/main/java/cwms/cda/api/ProjectController.java b/cwms-data-api/src/main/java/cwms/cda/api/ProjectController.java index 276499971..b297ed106 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/ProjectController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/ProjectController.java @@ -58,14 +58,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -112,7 +112,7 @@ private Timer.Context markAndTime(String subject) { @OpenApiResponse(status = STATUS_501, description = "request format is not" + " implemented")}, description = "Returns Projects Data", - tags = {TAG}) + tags = {TAG}, path = "/project") @Override public void getAll(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime(GET_ALL)) { @@ -143,7 +143,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError re = new CdaError("Error writing response"); logger.atSevere().withCause(ex).log("Failed to process request to retrieve Basins"); @@ -169,7 +169,8 @@ public void getAll(@NotNull Context ctx) { + "inputs provided the Project was not found."), @OpenApiResponse(status = STATUS_501, description = "request format is not " + "implemented")}, - description = "Retrieves requested Project", tags = {"Projects"}) + description = "Retrieves requested Project", tags = {"Projects"}, + path = "/peoject/{" + NAME + "}") @Override public void getOne(@NotNull Context ctx, @NotNull String name) { try (final Timer.Context ignored = markAndTime(GET_ONE)) { @@ -199,7 +200,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } } catch (IOException ex) { CdaError re = new CdaError("Error writing response"); @@ -220,8 +221,9 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @OpenApiParam(name = FAIL_IF_EXISTS, type = Boolean.class, description = "Create will fail if provided ID already exists. Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/project" ) @Override public void create(@NotNull Context ctx) { @@ -229,7 +231,7 @@ public void create(@NotNull Context ctx) { DSLContext dsl = getDslContext(ctx); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Project.class); Project project = Formats.parseContent(contentType, ctx.body(), Project.class); ProjectDao dao = new ProjectDao(dsl); @@ -255,8 +257,9 @@ public void create(@NotNull Context ctx) { }, required = true ), - method = HttpMethod.PATCH, - tags = {TAG} + methods = HttpMethod.PATCH, + tags = {TAG}, + path = "/project/{" + NAME + "}" ) @Override public void update(@NotNull Context ctx, @NotNull String oldName) { @@ -283,8 +286,9 @@ public void update(@NotNull Context ctx, @NotNull String oldName) { description = "Specifies the delete method used. " + "Defaults to \"DELETE_KEY\"") }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/project/{" + NAME + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String name) { @@ -301,6 +305,4 @@ public void delete(@NotNull Context ctx, @NotNull String name) { ctx.status(HttpServletResponse.SC_NO_CONTENT); } } - - } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/PropertyController.java b/cwms-data-api/src/main/java/cwms/cda/api/PropertyController.java index 6b1bcb941..0071154f1 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/PropertyController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/PropertyController.java @@ -52,15 +52,15 @@ import cwms.cda.data.dto.StatusResponse; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -83,14 +83,15 @@ public PropertyController(MetricRegistry metrics) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSON, from = Property.class) + @OpenApiContent(type = Formats.JSON, from = Property[].class) }) }, security = { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "Returns matching CWMS Property Data.", - tags = {TAG} + tags = {TAG}, + path = "/property" ) @Override public void getAll(Context ctx) { @@ -111,7 +112,7 @@ public void getAll(Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Properties", ex); @@ -143,7 +144,8 @@ public void getAll(Context ctx) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "Returns CWMS Property Data", - tags = {TAG} + tags = {TAG}, + path = "/property/{" + NAME + "}" ) @Override public void getOne(Context ctx, String name) { @@ -163,7 +165,7 @@ public void getOne(Context ctx, String name) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Property", ex); @@ -180,8 +182,9 @@ public void getOne(Context ctx, String name) { }, required = true), description = "Create CWMS Property", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAG}, + path = "/properties", responses = { @OpenApiResponse(status = STATUS_204, description = "Property successfully stored to CWMS.") } @@ -189,7 +192,7 @@ public void getOne(Context ctx, String name) { @Override public void create(Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Property.class); Property property = Formats.parseContent(contentType, ctx.body(), Property.class); DSLContext dsl = getDslContext(ctx); @@ -199,7 +202,6 @@ public void create(Context ctx) { "Property successfully stored to CWMS.", property.getName()); ctx.status(HttpServletResponse.SC_CREATED).json(re); } - } @OpenApi( @@ -213,7 +215,8 @@ public void create(Context ctx) { }, required = true), description = "Update CWMS Property", - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, + path = "/property/{" + NAME + "}", tags = {TAG}, responses = { @OpenApiResponse(status = STATUS_200, description = "Property successfully updated in CWMS.") @@ -223,7 +226,7 @@ public void create(Context ctx) { public void update(Context ctx, String name) { logUnusedPathParameter(ctx, NAME, "Body contains required information"); try (Timer.Context ignored = markAndTime(UPDATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Property.class); Property property = Formats.parseContent(contentType, ctx.body(), Property.class); DSLContext dsl = getDslContext(ctx); @@ -248,7 +251,8 @@ public void update(Context ctx, String name) { + "the property to be deleted."), }, description = "Delete CWMS Property", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, + path = "/properties/{" + NAME + "}", tags = {TAG}, responses = { @OpenApiResponse(status = STATUS_200, description = "Property successfully deleted from CWMS."), diff --git a/cwms-data-api/src/main/java/cwms/cda/api/PublishedController.java b/cwms-data-api/src/main/java/cwms/cda/api/PublishedController.java index ce857bcc6..fe7121cee 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/PublishedController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/PublishedController.java @@ -49,13 +49,13 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; +import io.javalin.http.HttpStatus; import io.javalin.http.Context; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -78,7 +78,7 @@ private Timer.Context markAndTime(String subject) { return Controllers.markAndTime(metrics, getClass().getName(), subject); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(@NotNull Context context) { try (final Timer.Context ignored = markAndTime(CREATE)) { @@ -86,7 +86,7 @@ public void create(@NotNull Context context) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(@NotNull Context context, @NotNull String s) { try (final Timer.Context ignored = markAndTime(DELETE)) { @@ -111,11 +111,12 @@ public void delete(@NotNull Context context, @NotNull String s) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = LocationToPublishedDataList.class) + @OpenApiContent(type = Formats.JSONV1, from = LocationToPublishedDataList[].class) }) }, description = "Returns matching time series identifiers for published data.", - tags = {TAG} + tags = {TAG}, + path = "/published" ) @Override public void getAll(@NotNull Context ctx) { @@ -125,7 +126,7 @@ public void getAll(@NotNull Context ctx) { String.class, "", metrics, name(PublishedController.class.getName(), GET_ALL)); if (!CwmsDTOPaginated.CURSOR_CHECK.invoke(cursor)) { ctx.json(new CdaError("cursor or page passed in but failed validation")) - .status(HttpCode.BAD_REQUEST); + .status(HttpStatus.BAD_REQUEST); return; } int pageSize = queryParamAsClass(ctx, new String[]{PAGE_SIZE}, Integer.class, DEFAULT_PAGE_SIZE, metrics, @@ -148,7 +149,7 @@ public void getAll(@NotNull Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context context, @NotNull String s) { try (final Timer.Context ignored = markAndTime(GET_ONE)) { @@ -156,7 +157,7 @@ public void getOne(@NotNull Context context, @NotNull String s) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context context, @NotNull String s) { try (final Timer.Context ignored = markAndTime(UPDATE)) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/RangeRequestUtil.java b/cwms-data-api/src/main/java/cwms/cda/api/RangeRequestUtil.java index 97cdbc6f0..c4e83b7f7 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/RangeRequestUtil.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/RangeRequestUtil.java @@ -1,7 +1,7 @@ package cwms.cda.api; import com.google.common.flogger.FluentLogger; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import java.io.IOException; import java.io.InputStream; @@ -42,7 +42,7 @@ public static void seekableStream(Context ctx, InputStream is, long isPostion, S if (ctx.header(Header.RANGE) == null) { // Not a range request. - ctx.res.setContentType(mediaType); + ctx.contentType(mediaType); if(isPostion > 0){ throw new IllegalArgumentException("Input stream position must be 0 for non-range requests"); @@ -53,7 +53,7 @@ public static void seekableStream(Context ctx, InputStream is, long isPostion, S // Chunked is a worse experience overall, seems like we should just set the length if we know it. ctx.header(Header.CONTENT_LENGTH, String.valueOf(totalBytes)); - IOUtils.copyLarge(is, (OutputStream) ctx.res.getOutputStream(), 0, totalBytes); + IOUtils.copyLarge(is, (OutputStream) ctx.outputStream(), 0, totalBytes); } else { String rangeHeader = ctx.header(Header.RANGE); @@ -79,7 +79,7 @@ public static void seekableStream(Context ctx, InputStream is, long isPostion, S ctx.header(Header.ACCEPT_RANGES, "bytes"); ctx.header(Header.CONTENT_RANGE, "bytes " + from + "-" + to + "/" + totalBytes); - ctx.res.setContentType(mediaType); + ctx.contentType(mediaType); ctx.header(Header.CONTENT_LENGTH, String.valueOf(Math.min(to - from + 1, totalBytes))); if(isPostion < from){ @@ -97,7 +97,7 @@ public static void seekableStream(Context ctx, InputStream is, long isPostion, S // stream from Oracle Blobs). // We do our own skipping and then have IOUtils copy. - IOUtils.copyLarge(is, (OutputStream) ctx.res.getOutputStream(), 0, len); + IOUtils.copyLarge(is, (OutputStream) ctx.outputStream(), 0, len); } } @@ -115,7 +115,7 @@ public static void seekableReader(Context ctx, Reader reader, long isPostion, St if (ctx.header(Header.RANGE) == null) { // Not a range request. - ctx.res.setContentType(mediaType); + ctx.contentType(mediaType); if(isPostion > 0){ throw new IllegalArgumentException("Input stream position must be 0 for non-range requests"); @@ -123,7 +123,7 @@ public static void seekableReader(Context ctx, Reader reader, long isPostion, St ctx.header(Header.CONTENT_LENGTH, String.valueOf(totalBytes)); - IOUtils.copyLarge(reader, ctx.res.getWriter(), 0, totalBytes); + IOUtils.copyLarge(reader, ctx.res().getWriter(), 0, totalBytes); } else { String rangeHeader = ctx.header(Header.RANGE); @@ -149,15 +149,15 @@ public static void seekableReader(Context ctx, Reader reader, long isPostion, St ctx.header(Header.ACCEPT_RANGES, "bytes"); ctx.header(Header.CONTENT_RANGE, "bytes " + from + "-" + to + "/" + totalBytes); - ctx.res.setContentType(mediaType); + ctx.contentType(mediaType); ctx.header(Header.CONTENT_LENGTH, String.valueOf(Math.min(to - from + 1, totalBytes))); - if(isPostion < from){ + if (isPostion < from) { skip(reader, from-isPostion); } long len = Math.min(to, totalBytes - 1) - from + 1; - IOUtils.copyLarge(reader, ctx.res.getWriter(), 0, len); + IOUtils.copyLarge(reader, ctx.res().getWriter(), 0, len); } } @@ -174,5 +174,4 @@ private static void skip(Reader reader, long toSkip) throws IOException { toSkip -= skipped; } } - } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/SpecifiedLevelController.java b/cwms-data-api/src/main/java/cwms/cda/api/SpecifiedLevelController.java index ba555094b..8bdfc9539 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/SpecifiedLevelController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/SpecifiedLevelController.java @@ -49,14 +49,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -105,7 +105,8 @@ private Timer.Context markAndTime(String subject) { } ) }, - tags = {TAG} + tags = {TAG}, + path = "/level/specified" ) @Override public void getAll(Context ctx) { @@ -128,7 +129,7 @@ public void getAll(Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Specified Levels", ex); @@ -138,7 +139,7 @@ public void getAll(Context ctx) { } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String templateId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -155,15 +156,17 @@ public void getOne(@NotNull Context ctx, @NotNull String templateId) { @OpenApiParam(name = FAIL_IF_EXISTS, type = Boolean.class, description = "Create will fail if provided ID already exists. Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/levels/specified" + ) @Override public void create(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(formatHeader, SpecifiedLevel.class); SpecifiedLevel deserialize = Formats.parseContent(contentType, body, SpecifiedLevel.class); @@ -184,8 +187,9 @@ public void create(@NotNull Context ctx) { + "owning office of the specified level to be renamed"), @OpenApiParam(name = SPECIFIED_LEVEL_ID, required = true, description = "The new specified level id.") }, - method = HttpMethod.PATCH, - tags = {TAG} + methods = HttpMethod.PATCH, + tags = {TAG}, + path = "/levels/specified/{" + SPECIFIED_LEVEL_ID + "}" ) @Override public void update(@NotNull Context ctx, @NotNull String oldSpecifiedLevelId) { @@ -211,8 +215,9 @@ public void update(@NotNull Context ctx, @NotNull String oldSpecifiedLevelId) { @OpenApiParam(name = OFFICE, required = true, description = "Specifies the " + "owning office of the timeseries identifier to be deleted"), }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/levels/specified/{" + SPECIFIED_LEVEL_ID + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String specifiedLevelId) { @@ -225,5 +230,4 @@ public void delete(@NotNull Context ctx, @NotNull String specifiedLevelId) { ctx.status(HttpServletResponse.SC_NO_CONTENT); } } - } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/StandardTextController.java b/cwms-data-api/src/main/java/cwms/cda/api/StandardTextController.java index 9aec0a06f..3483d61ae 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/StandardTextController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/StandardTextController.java @@ -53,14 +53,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -104,8 +104,9 @@ private Timer.Context markAndTime(String subject) { @OpenApiContent(type = Formats.JSONV2, from = StandardTextCatalog.class) } )}, - method = HttpMethod.GET, - tags = {TAG} + methods = {HttpMethod.GET}, + tags = {TAG}, + path = "/text" ) @Override public void getAll(Context ctx) { @@ -126,7 +127,7 @@ public void getAll(Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, TEXT_ERROR, ex); @@ -152,8 +153,9 @@ public void getAll(Context ctx) { @OpenApiContent(type = Formats.JSONV2, from = StandardTextValue.class) } )}, - method = HttpMethod.GET, - tags = {TAG} + methods = {HttpMethod.GET}, + tags = {TAG}, + path = "/text/{" + STANDARD_TEXT_ID + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String stdTextId) { @@ -170,7 +172,7 @@ public void getOne(@NotNull Context ctx, @NotNull String stdTextId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, TEXT_ERROR, ex); @@ -190,13 +192,14 @@ public void getOne(@NotNull Context ctx, @NotNull String stdTextId) { @OpenApiParam(name = FAIL_IF_EXISTS, type = Boolean.class, description = "Create will fail if provided ID already exists. Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/text/" ) @Override public void create(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); String body = ctx.body(); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(false); @@ -209,7 +212,7 @@ public void create(@NotNull Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context ctx, @NotNull String oldTextTimeSeriesId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -228,8 +231,9 @@ public void update(@NotNull Context ctx, @NotNull String oldTextTimeSeriesId) { @OpenApiParam(name = METHOD, required = true, description = "Specifies the delete method used.", type = JooqDao.DeleteMethod.class) }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/text/{" + STANDARD_TEXT_ID + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String stdTextId) { @@ -256,5 +260,4 @@ public void delete(@NotNull Context ctx, @NotNull String stdTextId) { ctx.status(HttpServletResponse.SC_NO_CONTENT); } } - } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/StateController.java b/cwms-data-api/src/main/java/cwms/cda/api/StateController.java index 0a05423f4..e6df60669 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/StateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/StateController.java @@ -39,11 +39,11 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiResponse; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -79,11 +79,11 @@ private Timer.Context markAndTime(String subject) { @OpenApiResponse(status = "" + HttpServletResponse.SC_OK, description = "A list of states.", content = { - @OpenApiContent(from = State.class, isArray = true, - type = Formats.JSONV2), + @OpenApiContent(from = State[].class, type = Formats.JSONV2), }), }, - tags = {"States"} + tags = {"States"}, + path = "/states" ) @Override public void getAll(@NotNull Context ctx) { @@ -101,28 +101,27 @@ public void getAll(@NotNull Context ctx) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String state) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context ctx, @NotNull String state) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(@NotNull Context ctx, @NotNull String state) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/StreamController.java b/cwms-data-api/src/main/java/cwms/cda/api/StreamController.java index 45015a2a5..c54e0ccd2 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/StreamController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/StreamController.java @@ -61,14 +61,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -109,12 +109,13 @@ private Timer.Context markAndTime(String subject) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = Stream.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = Stream.class) + @OpenApiContent(type = Formats.JSONV1, from = Stream[].class), + @OpenApiContent(type = Formats.JSON, from = Stream[].class) }) }, description = "Returns matching CWMS Stream Data for a Reservoir Project.", - tags = {TAG} + tags = {TAG}, + path = "/stream" ) @Override public void getAll(@NotNull Context ctx) { @@ -136,7 +137,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve streams", ex); @@ -159,12 +160,13 @@ public void getAll(@NotNull Context ctx) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = Stream.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = Stream.class) + @OpenApiContent(type = Formats.JSONV1, from = Stream[].class), + @OpenApiContent(type = Formats.JSON, from = Stream[].class) }) }, description = "Returns CWMS Stream Data", - tags = {TAG} + tags = {TAG}, + path = "/stream/{" + NAME + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String streamId) { @@ -184,7 +186,7 @@ public void getOne(@NotNull Context ctx, @NotNull String streamId) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve stream", ex); @@ -204,16 +206,17 @@ public void getOne(@NotNull Context ctx, @NotNull String streamId) { description = "Create will fail if provided ID already exists. Default: true") }, description = "Create CWMS Stream", - method = HttpMethod.POST, + methods = {HttpMethod.POST}, tags = {TAG}, responses = { @OpenApiResponse(status = STATUS_204, description = "Stream successfully stored to CWMS.") - } + }, + path = "/stream" ) @Override public void create(Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Stream.class); Stream stream = Formats.parseContent(contentType, ctx.body(), Stream.class); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); @@ -224,7 +227,6 @@ public void create(Context ctx) { stream.getId().getName()); ctx.status(HttpServletResponse.SC_CREATED).json(re); } - } @OpenApi( @@ -238,11 +240,12 @@ public void create(Context ctx) { @OpenApiParam(name = NAME, required = true, description = "Specifies the new stream-id. ") }, description = "Rename CWMS Stream", - method = HttpMethod.PATCH, + methods = {HttpMethod.PATCH}, tags = {TAG}, responses = { @OpenApiResponse(status = STATUS_204, description = "Stream successfully renamed in CWMS.") - } + }, + path = "/stream/{" + NAME + "}" ) @Override public void update(@NotNull Context ctx, @NotNull String streamId) { @@ -270,13 +273,14 @@ public void update(@NotNull Context ctx, @NotNull String streamId) { type = JooqDao.DeleteMethod.class) }, description = "Delete CWMS Stream", - method = HttpMethod.DELETE, + methods = {HttpMethod.DELETE}, tags = {TAG}, responses = { @OpenApiResponse(status = STATUS_200, description = "Stream successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " + "inputs provided the stream was not found.") - } + }, + path = "/stream/{" + NAME + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String streamId) { @@ -306,4 +310,4 @@ public void delete(@NotNull Context ctx, @NotNull String streamId) { ctx.status(HttpServletResponse.SC_OK).json(re); } } -} \ No newline at end of file +} diff --git a/cwms-data-api/src/main/java/cwms/cda/api/StreamLocationController.java b/cwms-data-api/src/main/java/cwms/cda/api/StreamLocationController.java index be9da11d5..8c86daae7 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/StreamLocationController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/StreamLocationController.java @@ -55,14 +55,14 @@ import cwms.cda.data.dto.stream.StreamLocation; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -92,12 +92,13 @@ public StreamLocationController(MetricRegistry metrics) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = StreamLocation.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = StreamLocation.class) + @OpenApiContent(type = Formats.JSONV1, from = StreamLocation[].class), + @OpenApiContent(type = Formats.JSON, from = StreamLocation[].class) }) }, description = "Returns matching CWMS Stream Location Data for a Reservoir Project.", - tags = {TAG} + tags = {TAG}, + path = "/stream/location" ) @Override public void getAll(Context ctx) { @@ -121,7 +122,7 @@ public void getAll(Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve stream locations", ex); @@ -147,12 +148,13 @@ public void getAll(Context ctx) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = StreamLocation.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = StreamLocation.class) + @OpenApiContent(type = Formats.JSONV1, from = StreamLocation[].class), + @OpenApiContent(type = Formats.JSON, from = StreamLocation[].class) }) }, description = "Returns CWMS Stream Location Data", - tags = {TAG} + tags = {TAG}, + path = "/stream/location/{" + NAME + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String locationId) { @@ -175,7 +177,7 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve stream location", ex); @@ -195,8 +197,9 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { description = "Create will fail if provided ID already exists. Default: true") }, description = "Create CWMS Stream Location", - method = HttpMethod.POST, + methods = {HttpMethod.POST}, tags = {TAG}, + path = "/stream/location", responses = { @OpenApiResponse(status = STATUS_201, description = "Stream Location successfully stored to CWMS.") } @@ -204,7 +207,7 @@ public void getOne(@NotNull Context ctx, @NotNull String locationId) { @Override public void create(Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, StreamLocation.class); StreamLocation streamLocation = Formats.parseContent(contentType, ctx.body(), StreamLocation.class); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); @@ -228,8 +231,9 @@ public void create(Context ctx) { }, required = true), description = "Update CWMS Stream Location", - method = HttpMethod.PATCH, + methods = {HttpMethod.PATCH}, tags = {TAG}, + path = "/stream/location/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Updated Stream Location") } @@ -238,7 +242,7 @@ public void create(Context ctx) { public void update(Context ctx, @NotNull String name) { logUnusedPathParameter(ctx, NAME, "Body contains required information"); try (Timer.Context ignored = markAndTime(METHOD + "update")) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, StreamLocation.class); StreamLocation streamLocation = Formats.parseContent(contentType, ctx.body(), StreamLocation.class); DSLContext dsl = getDslContext(ctx); @@ -262,8 +266,9 @@ public void update(Context ctx, @NotNull String name) { + "stream location to be deleted.") }, description = "Delete CWMS Stream Location", - method = HttpMethod.DELETE, + methods = {HttpMethod.DELETE}, tags = {TAG}, + path = "/stream/location/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Stream Location successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Stream Location not found.") diff --git a/cwms-data-api/src/main/java/cwms/cda/api/StreamReachController.java b/cwms-data-api/src/main/java/cwms/cda/api/StreamReachController.java index cf075e78a..c1c087144 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/StreamReachController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/StreamReachController.java @@ -57,14 +57,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -101,12 +101,13 @@ private Timer.Context markAndTime(String subject) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = StreamReach.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = StreamReach.class) + @OpenApiContent(type = Formats.JSONV1, from = StreamReach[].class), + @OpenApiContent(type = Formats.JSON, from = StreamReach[].class) }) }, description = "Returns matching CWMS Stream Reach Data for a Reservoir Project.", - tags = {TAG} + tags = {TAG}, + path = "/stream/reach" ) @Override public void getAll(@NotNull Context ctx) { @@ -128,7 +129,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Stream Reaches", ex); @@ -153,12 +154,13 @@ public void getAll(@NotNull Context ctx) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = StreamReach.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = StreamReach.class) + @OpenApiContent(type = Formats.JSONV1, from = StreamReach[].class), + @OpenApiContent(type = Formats.JSON, from = StreamReach[].class) }) }, description = "Returns CWMS Stream Reach Data", - tags = {TAG} + tags = {TAG}, + path = "/stream/reach/{" + NAME + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String reachId) { @@ -179,7 +181,7 @@ public void getOne(@NotNull Context ctx, @NotNull String reachId) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Stream Reach", ex); @@ -199,8 +201,9 @@ public void getOne(@NotNull Context ctx, @NotNull String reachId) { description = "Create will fail if provided ID already exists. Default: true") }, description = "Create CWMS Stream Reach", - method = HttpMethod.POST, + methods = {HttpMethod.POST}, tags = {TAG}, + path = "/stream/reach", responses = { @OpenApiResponse(status = STATUS_201, description = "Stream Reach successfully stored to CWMS.") } @@ -208,7 +211,7 @@ public void getOne(@NotNull Context ctx, @NotNull String reachId) { @Override public void create(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, StreamReach.class); StreamReach streamReach = Formats.parseContent(contentType, ctx.body(), StreamReach.class); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); @@ -232,8 +235,9 @@ public void create(@NotNull Context ctx) { @OpenApiParam(name = NAME, required = true, description = "Specifies the new reach-id. ") }, description = "Rename CWMS Stream Reach", - method = HttpMethod.PATCH, + methods = {HttpMethod.PATCH}, tags = {TAG}, + path = "/stream/reach/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Stream Reach successfully renamed in CWMS.") } @@ -261,8 +265,9 @@ public void update(@NotNull Context ctx, @NotNull String reachId) { + "the stream reach to be deleted.") }, description = "Delete CWMS Stream Reach", - method = HttpMethod.DELETE, + methods = {HttpMethod.DELETE}, tags = {TAG}, + path = "/stream/reach/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Stream Reach successfully deleted from CWMS.") } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesCategoryController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesCategoryController.java index b93c3adf8..47a9ed7cc 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesCategoryController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesCategoryController.java @@ -39,14 +39,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import java.util.Optional; @@ -80,14 +80,16 @@ private Timer.Context markAndTime(String subject) { + " all offices shall be returned."),}, responses = { @OpenApiResponse(status = STATUS_200, - content = {@OpenApiContent(isArray = true, from = TimeSeriesCategory.class, - type = Formats.JSON) + content = {@OpenApiContent(from = TimeSeriesCategory[].class, type = Formats.JSON) }), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " + "inputs provided the categories were not found."), @OpenApiResponse(status = STATUS_501, description = "request format is not " + "implemented")}, description = "Returns CWMS timeseries category " - + "Data", tags = {TAG}) + + "Data", + tags = {TAG}, + path = "/timeseries/category" + ) @Override public void getAll(@NotNull Context ctx) { try (final Timer.Context timeContext = markAndTime(GET_ALL)) { @@ -110,7 +112,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve TimeSeries Categories", ex); @@ -140,7 +142,8 @@ public void getAll(@NotNull Context ctx) { + "inputs provided the timeseries category was not found."), @OpenApiResponse(status = STATUS_501, description = "request format is not " + "implemented")}, - description = "Retrieves requested timeseries category", tags = {TAG}) + description = "Retrieves requested timeseries category", tags = {TAG}, + path = "/timeseries/category/{" + CATEGORY_ID + "}") @Override public void getOne(@NotNull Context ctx, @NotNull String categoryId) { try (final Timer.Context timeContext = markAndTime(GET_ONE)) { @@ -163,7 +166,7 @@ public void getOne(@NotNull Context ctx, @NotNull String categoryId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { CdaError re = new CdaError("Unable to find category based on parameters given"); logger.atInfo().log("%s%nfor request %s", re, ctx.fullUrl()); @@ -189,7 +192,8 @@ public void getOne(@NotNull Context ctx, @NotNull String categoryId) { @OpenApiParam(name = IGNORE_NULLS, type = Boolean.class, description = "Ignore null values in the request body. Default: true") }, - method = HttpMethod.POST, + methods = {HttpMethod.POST}, + path = "/timeseries/category", tags = {TAG} ) @Override @@ -197,7 +201,7 @@ public void create(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(formatHeader, TimeSeriesCategory.class); @@ -226,15 +230,16 @@ public void create(@NotNull Context ctx) { description = "Ignore null values in the request body. Default: true") }, - method = HttpMethod.PATCH, - tags = {TAG} + methods = {HttpMethod.PATCH}, + tags = {TAG}, + path = "/timeseries/category/{" + CATEGORY_ID + "}" ) @Override public void update(@NotNull Context ctx, @NotNull String categoryId) { try (Timer.Context ignored = markAndTime(UPDATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); String body = ctx.body(); boolean ignoreNulls = ctx.queryParamAsClass(IGNORE_NULLS, Boolean.class).getOrDefault(true); @@ -258,8 +263,9 @@ public void update(@NotNull Context ctx, @NotNull String categoryId) { @OpenApiParam(name = CASCADE_DELETE, type = Boolean.class, description = "Specifies whether to delete any time series groups in this time series category. Default: false"), }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = {HttpMethod.DELETE}, + tags = {TAG}, + path = "/timeseries/category/{" + CATEGORY_ID + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String categoryId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesController.java index f5871a278..c7ea4b923 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesController.java @@ -30,17 +30,16 @@ import cwms.cda.formatters.Formats; import cwms.cda.helpers.DateUtils; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; -import io.javalin.core.validation.JavalinValidation; -import io.javalin.core.validation.Validator; +import io.javalin.http.Header; +import io.javalin.validation.Validator; import io.javalin.http.Context; import io.javalin.http.HandlerType; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.io.StringWriter; import java.net.URISyntaxException; @@ -128,10 +127,11 @@ public TimeSeriesController(MetricRegistry metrics) { requestResultSize = this.metrics.histogram((name(className, RESULTS, SIZE))); } - static { - JavalinValidation.register(StoreRule.class, StoreRule::getStoreRule); - JavalinValidation.register(VerticalDatum.class, VerticalDatum::getVerticalDatum); - } + // TODO: move to config +// static { +// JavalinValidation.register(StoreRule.class, StoreRule::getStoreRule); +// JavalinValidation.register(VerticalDatum.class, VerticalDatum::getVerticalDatum); +// } private Timer.Context markAndTime(String subject) { return Controllers.markAndTime(metrics, getClass().getName(), subject); @@ -166,7 +166,7 @@ private Timer.Context markAndTime(String subject) { + "this parameter is provided it is assumed that the data is in the Datum named by the argument " + "and should be converted to the as-stored datum before being saved.") }, - method = HttpMethod.POST, + methods = {HttpMethod.POST}, path = "/timeseries", tags = TAG ) @@ -201,7 +201,7 @@ public void create(@NotNull Context ctx) { protected DSLContext getDslContext(Context ctx) { String office = null; - if (ctx.handlerType() == HandlerType.GET + if (ctx.method() == HandlerType.GET && ctx.attribute(AuthDao.DATA_API_PRINCIPAL) != null) { office = ctx.queryParamAsClass(OFFICE, String.class) .getOrDefault(ctx.attribute(ApiServlet.OFFICE_ID)); @@ -249,7 +249,7 @@ protected TimeSeriesDao getTimeSeriesDao(DSLContext dsl) { + "('True'/'False') specifying whether to delete protected data. " + "Default is False") }, - method = HttpMethod.DELETE, + methods = {HttpMethod.DELETE}, path = "/timeseries/{timeseries}", tags = TAG ) @@ -432,7 +432,7 @@ public void delete(@NotNull Context ctx, @NotNull String timeseries) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.GET, + methods = {HttpMethod.GET}, path = "/timeseries", tags = TAG ) @@ -558,7 +558,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { String office = ctx.queryParam(OFFICE); @@ -599,7 +599,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } addDeprecatedContentTypeWarning(ctx, contentType); @@ -630,7 +630,7 @@ private void streamCsv(@NotNull Context ctx, CsvConfiguration csvConfig, int bat ctx.header(Header.CONTENT_TYPE, Formats.CSV + "; charset=UTF-8"); ctx.header("X-Stream-Batch-Size", String.valueOf(batchSize)); try (stream) { - IOUtils.copy(stream, ctx.res.getOutputStream()); + IOUtils.copy(stream, ctx.outputStream()); } catch (IOException e) { throw new RuntimeException(e); } @@ -682,7 +682,7 @@ private void addLinkHeader(@NotNull Context ctx, TimeSeries ts, ContentType cont } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String id) { @@ -718,12 +718,12 @@ public void getOne(@NotNull Context ctx, @NotNull String id) { + "this parameter is provided it is assumed that the data is in the Datum named by the argument " + "and should be converted to the as-stored datum before being saved.") }, - method = HttpMethod.PATCH, + methods = {HttpMethod.PATCH}, path = "/timeseries/{timeseries}", tags = TAG ) @Override - public void update(@NotNull Context ctx, @NotNull String id) { + public void update(@NotNull Context ctx, @NotNull String timeseries) { try (final Timer.Context ignored = markAndTime(UPDATE)) { DSLContext dsl = getDslContext(ctx); @@ -752,9 +752,9 @@ public void update(@NotNull Context ctx, @NotNull String id) { } private TimeSeries deserializeTimeSeries(Context ctx) throws IOException { - String contentTypeHeader = ctx.req.getContentType(); + String contentTypeHeader = ctx.contentType(); StringWriter writer = new StringWriter(); - IOUtils.copy(ctx.bodyAsInputStream(), writer, StandardCharsets.UTF_8); + IOUtils.copy(ctx.bodyInputStream(), writer, StandardCharsets.UTF_8); if (writer.toString().contains("data-entry-date")) { throw new IllegalArgumentException("Data entry date is not allowed in the request"); } @@ -770,11 +770,11 @@ private TimeSeries deserializeTimeSeries(Context ctx) throws IOException { * @return a URL that references the same query, but with a different "page" parameter */ public String buildRequestUrl(Context ctx, TimeSeries ts, String cursor) throws URISyntaxException { - URIBuilder builder = new URIBuilder(ctx.req.getRequestURL().toString()); // requestURL stops just before '?' + URIBuilder builder = new URIBuilder(ctx.url()); // requestURL stops just before '?' // Instead of adding specific parameters and risk forgetting to add one to this method // Lets add all the previous parameters and then (cont.) - builder.setParameters(URLEncodedUtils.parse(ctx.req.getQueryString(), StandardCharsets.UTF_8)); + builder.setParameters(URLEncodedUtils.parse(ctx.queryString(), StandardCharsets.UTF_8)); // (cont.) override or add the page parameter with the new cursor value if (cursor != null && !cursor.isEmpty()) { From 64efa1275446a84290fd7a1061c850f8d3787b2e Mon Sep 17 00:00:00 2001 From: "Michael A. Neilson" Date: Wed, 30 Sep 2026 19:42:10 +0000 Subject: [PATCH 05/69] Disable ci build while changes are worked through. --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 77ef770e1..d9c356c96 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,6 +10,7 @@ on: jobs: build: + if: false strategy: fail-fast: false matrix: @@ -90,6 +91,7 @@ jobs: report_paths: '**/TEST-*.xml' detailed_summary: true open-api-static-analysis: + if: false name: OpenApi Static Analysis Tests runs-on: ubuntu-latest env: @@ -115,6 +117,7 @@ jobs: report_paths: '**/TEST-*.xml' detailed_summary: true build-docker-image: + if: false runs-on: ubuntu-latest steps: - name: checkout code @@ -122,6 +125,7 @@ jobs: - name: Build docker image run: docker build -t cda:build-latest . build-schema-migration-image: + if: false runs-on: ubuntu-latest steps: - name: checkout code From ef9d1d7d86d44e5d57326540c5099434b66b5fc4 Mon Sep 17 00:00:00 2001 From: "Michael A. Neilson" Date: Wed, 30 Sep 2026 20:35:07 +0000 Subject: [PATCH 06/69] Another batch. --- .../api/BinaryTimeSeriesValueController.java | 3 -- .../api/rating/RateTimeSeriesController.java | 23 ++++---- .../cda/api/rating/RateValuesController.java | 23 ++++---- .../cwms/cda/api/rating/RatingController.java | 52 +++++++++++-------- .../RatingEffectiveDatesController.java | 15 +++--- .../api/rating/RatingLatestController.java | 21 ++++---- .../api/rating/RatingMetadataController.java | 23 ++++---- .../cda/api/rating/RatingSpecController.java | 39 +++++++------- .../api/rating/RatingTemplateController.java | 41 ++++++++------- .../ReverseRateTimeSeriesController.java | 25 ++++----- .../rating/ReverseRateValuesController.java | 25 ++++----- .../java/cwms/cda/api/rss/RssHandler.java | 24 ++++----- .../TextTimeSeriesController.java | 8 +-- .../TextTimeSeriesControllerV1.java | 40 ++++++++------ .../TextTimeSeriesControllerV2.java | 41 +++++++++------ .../TextTimeSeriesValueController.java | 13 ++--- .../TimeSeriesGroupController.java | 16 +++--- .../TimeSeriesGroupControllerV1.java | 46 +++++++++------- .../TimeSeriesGroupControllerV2.java | 46 ++++++++++------ .../TimeSeriesProfileCatalogController.java | 19 ++++--- .../TimeSeriesProfileController.java | 17 +++--- .../TimeSeriesProfileCreateController.java | 15 +++--- .../TimeSeriesProfileDeleteController.java | 11 ++-- ...eriesProfileInstanceCatalogController.java | 19 ++++--- .../TimeSeriesProfileInstanceController.java | 17 +++--- ...SeriesProfileInstanceCreateController.java | 15 +++--- ...SeriesProfileInstanceDeleteController.java | 13 ++--- ...eSeriesProfileParserCatalogController.java | 23 ++++---- .../TimeSeriesProfileParserController.java | 19 +++---- ...meSeriesProfileParserCreateController.java | 17 +++--- ...meSeriesProfileParserDeleteController.java | 16 +++--- .../AccountingCatalogController.java | 22 ++++---- .../AccountingCreateController.java | 18 +++---- .../WaterContractCatalogController.java | 16 +++--- .../watersupply/WaterContractController.java | 18 +++---- .../WaterContractCreateController.java | 17 +++--- .../WaterContractDeleteController.java | 8 +-- .../WaterContractTypeCatalogController.java | 18 +++---- .../WaterContractTypeCreateController.java | 17 +++--- .../WaterContractTypeDeleteController.java | 11 ++-- .../WaterContractUpdateController.java | 18 +++---- .../WaterPumpDisassociateController.java | 12 ++--- .../WaterUserCatalogController.java | 18 +++---- .../api/watersupply/WaterUserController.java | 18 +++---- .../WaterUserCreateController.java | 16 +++--- .../WaterUserDeleteController.java | 8 +-- .../WaterUserUpdateController.java | 18 +++---- 47 files changed, 518 insertions(+), 460 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesValueController.java b/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesValueController.java index 32bf79ba6..efa7c571d 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesValueController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/BinaryTimeSeriesValueController.java @@ -26,7 +26,6 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; -import com.google.common.flogger.FluentLogger; import cwms.cda.api.errors.CdaError; import cwms.cda.data.dao.BlobDao; import cwms.cda.data.dao.StreamConsumer; @@ -46,8 +45,6 @@ public class BinaryTimeSeriesValueController extends BaseHandler { - private static final FluentLogger LOGGER = FluentLogger.forEnclosingClass(); - public BinaryTimeSeriesValueController(MetricRegistry metrics) { super(metrics); } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/RateTimeSeriesController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/RateTimeSeriesController.java index 35a0537d8..357ee08b7 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/RateTimeSeriesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/RateTimeSeriesController.java @@ -42,15 +42,15 @@ import cwms.cda.data.dto.rating.RatedOutputTimeSeries; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -91,8 +91,9 @@ public RateTimeSeriesController(MetricRegistry metrics) { "each corresponding to an independent parameter in the rating curve." + "The output format `RatedOutputTimeSeries` will contain a singular double array corresponding to the " + "dependent parameter of the rating curve. ", - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/ratings/rate/{" + OFFICE + "}/{" + RATING_ID + "}" ) @Override public void handle(@NotNull Context ctx) throws Exception { @@ -101,7 +102,7 @@ public void handle(@NotNull Context ctx) throws Exception { RateDao ratingDao = new RateDao(dsl); String office = ctx.pathParam(OFFICE); String ratingId = ctx.pathParam(RATING_ID); - String contentTypeHeader = ctx.req.getContentType(); + String contentTypeHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(contentTypeHeader, RateInputTimeSeries.class); RateInputTimeSeries input = Formats.parseContent(contentType, body, RateInputTimeSeries.class); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/RateValuesController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/RateValuesController.java index f5363eb39..7e1799d8a 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/RateValuesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/RateValuesController.java @@ -42,15 +42,15 @@ import cwms.cda.data.dto.rating.RatedOutputValues; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -91,8 +91,9 @@ public RateValuesController(MetricRegistry metrics) { "in the rating curve. " + "The output format `RatedOutputTimeSeries` will contain a singular double array corresponding to the " + "dependent parameter of the rating curve. ", - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/ratings/rate/{" + OFFICE + "}/{" + RATING_ID + "}" ) @Override public void handle(@NotNull Context ctx) throws Exception { @@ -101,7 +102,7 @@ public void handle(@NotNull Context ctx) throws Exception { RateDao ratingDao = new RateDao(dsl); String office = ctx.pathParam(OFFICE); String ratingId = ctx.pathParam(RATING_ID); - String contentTypeHeader = ctx.req.getContentType(); + String contentTypeHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(contentTypeHeader, RateInputValues.class); RateInputValues input = Formats.parseContent(contentType, body, RateInputValues.class); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingController.java index 0ba1e3e88..2dac93e93 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingController.java @@ -78,17 +78,17 @@ import cwms.cda.helpers.DateUtils; import hec.data.RatingException; import hec.data.cwmsRating.RatingSet; -import io.javalin.core.util.Header; -import io.javalin.core.validation.JavalinValidation; +import io.javalin.http.Header; import io.javalin.http.BadRequestResponse; import io.javalin.http.Context; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import java.time.Instant; import java.util.HashMap; @@ -96,6 +96,8 @@ import javax.servlet.http.HttpServletResponse; import mil.army.usace.hec.cwms.rating.io.xml.RatingXmlFactory; import mil.army.usace.hec.metadata.VerticalDatumException; +import usace.cwms.db.jooq.codegen.udt.RATING_SPEC_T; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jooq.DSLContext; @@ -106,10 +108,11 @@ public class RatingController extends BaseCrudHandler { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); static final String TAG = "Ratings"; - static { - JavalinValidation.register(RatingSet.DatabaseLoadMethod.class, - RatingController::getDatabaseLoadMethod); - } + // TODO: moves to config + // static { + // JavalinValidation.register(RatingSet.DatabaseLoadMethod.class, + // RatingController::getDatabaseLoadMethod); + // } public RatingController(MetricRegistry metrics) { super(metrics); @@ -148,7 +151,7 @@ protected RatingDao getRatingDao(DSLContext dsl) { + "this parameter is provided it is assumed that the data is in the Datum named by the argument " + "and should be converted to the as-stored datum before being saved.") }, - method = HttpMethod.POST, path = "/ratings", tags = {TAG}, + methods = HttpMethod.POST, path = "/ratings", tags = {TAG}, responses = { @OpenApiResponse(status = STATUS_201, description = "Rating Set successfully stored to CWMS.") }) @@ -235,8 +238,9 @@ private static RatingsDocument removeTemplates(RatingsDocument ratings) { + BEGIN + ", " + END + ", or " + VERSION_DATE + " parameters do not include " + "offset or time zone information. Defaults to UTC."), }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/ratings/{" + RATING_ID + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String ratingSpecId) { @@ -311,7 +315,8 @@ public void delete(@NotNull Context ctx, @NotNull String ratingSpecId) { + "parameters did not find a rating table."), @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented")}, - tags = {TAG}) + tags = {TAG}, + path = "/ratings") @Override public void getAll(@NotNull Context ctx) { @@ -358,7 +363,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException e) { CdaError re = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Ratings", e); @@ -406,7 +411,8 @@ public void getAll(@NotNull Context ctx) { @OpenApiContent(type = Formats.XMLV2)})}, description = "Returns CWMS Rating Data. Supports accept header formatting. " + "For more information about accept header usage, see this page.", - tags = {TAG}) + tags = {TAG}, + path = "/ratings/{" + RATING_ID + "}") @Override public void getOne(@NotNull Context ctx, @NotNull String rating) { @@ -434,10 +440,10 @@ public void getOne(@NotNull Context ctx, @NotNull String rating) { String body = getRatingSetString(ctx, method, officeId, rating, beginInstant, endInstant, verticalDatum); if (body != null) { - ctx.status(HttpCode.OK); + ctx.status(HttpStatus.OK); byte[] bytes = body.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } } catch (IOException e) { CdaError re = ExceptionTraceSupport.buildError(ctx, @@ -507,7 +513,7 @@ private String getRatingSetString(Context ctx, RatingSet.DatabaseLoadMethod meth retval = RatingXmlFactory.toXml(ratingSet, " "); } } else { - ctx.status(HttpCode.NOT_FOUND); + ctx.status(HttpStatus.NOT_FOUND); } } catch (RatingException e) { CdaError re = ExceptionTraceSupport.buildError(ctx, @@ -574,7 +580,7 @@ private RatingSet getRatingSet(Context ctx, RatingSet.DatabaseLoadMethod method, + "this parameter is provided it is assumed that the data is in the Datum named by the argument " + "and should be converted to the as-stored datum before being saved.") }, - method = HttpMethod.PATCH, path = "/ratings", tags = {TAG}) + methods = HttpMethod.PATCH, path = "/ratings", tags = {TAG}) public void update(@NotNull Context ctx, @NotNull String ratingId) { logUnusedPathParameter(ctx, RATING_ID, "Body contains required information"); try (final Timer.Context ignored = markAndTime(UPDATE)) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingEffectiveDatesController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingEffectiveDatesController.java index 2d921604f..3e55d8f61 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingEffectiveDatesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingEffectiveDatesController.java @@ -23,13 +23,13 @@ import cwms.cda.data.dto.rating.RatingEffectiveDatesMap; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.time.Instant; import javax.servlet.http.HttpServletResponse; @@ -71,7 +71,8 @@ private Timer.Context markAndTime() { }) }, description = "Returns mapping of office -> spec id -> effective date-times for all matching offices and spec ids.", - tags = {RatingController.TAG} + tags = {RatingController.TAG}, + path = "/ratings/effectives" // TODO: check ) @Override public void handle(@NotNull Context ctx) throws Exception { @@ -93,7 +94,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve rating effective dates", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingLatestController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingLatestController.java index d1eb4e838..a13b3bfce 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingLatestController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingLatestController.java @@ -44,14 +44,14 @@ import cwms.cda.data.dao.RatingSetDao; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -92,7 +92,8 @@ protected RatingDao getRatingDao(DSLContext dsl) { @OpenApiContent(type = Formats.XMLV2)}) }, description = "Returns CWMS Rating Data", - tags = {TAG}) + tags = {TAG}, + path = "/ratings/latest/{" + RATING_ID + "}") @Override public void handle(@NotNull Context ctx) throws Exception { try (final Timer.Context ignored = markAndTime(GET_ONE)) { @@ -103,7 +104,7 @@ public void handle(@NotNull Context ctx) throws Exception { String officeId = requiredParam(ctx, OFFICE); if (!contentType.toString().equals(Formats.JSONV2) && !contentType.toString().equals(Formats.XMLV2)) { - ctx.status(HttpCode.UNSUPPORTED_MEDIA_TYPE); + ctx.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE); } String body = getLatestRatingSet(ctx, officeId, rating, contentType); @@ -113,9 +114,9 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = body.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { - ctx.status(HttpCode.NOT_FOUND); + ctx.status(HttpStatus.NOT_FOUND); } } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Rating", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingMetadataController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingMetadataController.java index ae5efd48f..51c080d55 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingMetadataController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingMetadataController.java @@ -51,12 +51,12 @@ import cwms.cda.formatters.Formats; import cwms.cda.helpers.DateUtils; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.time.ZonedDateTime; import javax.servlet.http.HttpServletResponse; @@ -124,7 +124,8 @@ private Timer.Context markAndTime(String subject) { RatingMetadataList.class) } )}, - tags = {"Ratings"} + tags = {"Ratings"}, + path = "/ratings/meta-data" // TODO: check ) @Override public void getAll(Context ctx) { @@ -168,7 +169,7 @@ public void getAll(Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve rating metadata", ex); @@ -178,7 +179,7 @@ public void getAll(Context ctx) { } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(Context ctx, String ratingId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -190,19 +191,19 @@ protected RatingMetadataDao getDao(DSLContext dsl) { } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(Context ctx, String locationCode) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(Context ctx, String locationCode) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingSpecController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingSpecController.java index 2e6923c48..8e8fccfaa 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingSpecController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingSpecController.java @@ -41,15 +41,14 @@ import cwms.cda.formatters.Formats; import cwms.cda.formatters.FormattingException; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; - +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.io.OutputStream; import java.util.Optional; @@ -115,7 +114,8 @@ private Timer.Context markAndTime(String subject) { @OpenApiContent(type = Formats.XMLV2, from = RatingSpecs.class) } )}, - tags = {TAG} + tags = {TAG}, + path = "/ratings/spec" ) @Override public void getAll(Context ctx) { @@ -143,7 +143,7 @@ public void getAll(Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException e) { CdaError re = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Ratings", e); @@ -172,7 +172,8 @@ public void getAll(Context ctx) { } ) }, - tags = {TAG} + tags = {TAG}, + path = "/ratings/spec/{" + RATING_ID + "}" ) @Override public void getOne(Context ctx, @NotNull String ratingId) { @@ -197,7 +198,7 @@ public void getOne(Context ctx, @NotNull String ratingId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - OutputStream os = ctx.res.getOutputStream(); + OutputStream os = ctx.outputStream(); if (os != null) { os.write(bytes); } else { @@ -235,15 +236,16 @@ protected RatingSpecDao getRatingSpecDao(DSLContext dsl) { @OpenApiParam(name = FAIL_IF_EXISTS, type = Boolean.class, description = "Create will fail if provided ID already exists. Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/ratings/spec" ) @Override public void create(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String contentTypeHeader = ctx.req.getContentType(); + String contentTypeHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(contentTypeHeader, RatingSpec.class); @@ -269,7 +271,7 @@ public void create(@NotNull Context ctx) { } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(Context ctx, @NotNull String locationCode) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -286,8 +288,9 @@ public void update(Context ctx, @NotNull String locationCode) { type = JooqDao.DeleteMethod.class) }, description = "Deletes requested rating specification", - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/ratings/spec/{" + RATING_ID + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String ratingSpecId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingTemplateController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingTemplateController.java index d0386e4fb..de6d74c41 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingTemplateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/RatingTemplateController.java @@ -43,14 +43,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.Optional; import com.google.common.flogger.FluentLogger; @@ -109,7 +109,8 @@ private Timer.Context markAndTime(String subject) { Formats.JSONV2), } )}, - tags = {TAG} + tags = {TAG}, + path = "/rating/template" // TODO: fix ) @Override public void getAll(Context ctx) { @@ -137,7 +138,7 @@ public void getAll(Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError re = new CdaError("Error while writing response "); logger.atInfo().log("%s%sfor request %s", re, System.lineSeparator(), ctx.fullUrl()); @@ -165,11 +166,11 @@ private RatingTemplateDao getRatingTemplateDao(DSLContext dsl) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, from = RatingTemplate.class, - type = Formats.JSONV2), + @OpenApiContent(from = RatingTemplate[].class, type = Formats.JSONV2), } )}, - tags = {TAG} + tags = {TAG}, + path = "/rating/template" // TODO: Fix ) @Override public void getOne(Context ctx, @NotNull String templateId) { @@ -195,7 +196,7 @@ public void getOne(Context ctx, @NotNull String templateId) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { CdaError re = new CdaError("Unable to find Rating Template based on " + "parameters given"); @@ -221,15 +222,16 @@ public void getOne(Context ctx, @NotNull String templateId) { @OpenApiParam(name = FAIL_IF_EXISTS, type = Boolean.class, description = "Create will fail if provided ID already exists. Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/ratings/template" // TODO: check ) @Override public void create(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime(CREATE)){ DSLContext dsl = getDslContext(ctx); - String reqContentType = ctx.req.getContentType(); + String reqContentType = ctx.contentType(); String formatHeader = reqContentType != null ? reqContentType : Formats.XMLV2; String body = ctx.body(); String xml = translateToXml(body, formatHeader); @@ -264,7 +266,7 @@ private static String translateJsonToXml(String body) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context ctx, @NotNull String locationCode) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -281,8 +283,9 @@ public void update(@NotNull Context ctx, @NotNull String locationCode) { type = JooqDao.DeleteMethod.class) }, description = "Deletes requested rating specification", - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/ratings/template/{" + TEMPLATE_ID + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String ratingTemplateId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/ReverseRateTimeSeriesController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/ReverseRateTimeSeriesController.java index 554867814..3d1aa8d04 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/ReverseRateTimeSeriesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/ReverseRateTimeSeriesController.java @@ -46,15 +46,15 @@ import cwms.cda.data.dto.rating.RatedOutputTimeSeries; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -97,8 +97,9 @@ public ReverseRateTimeSeriesController(MetricRegistry metrics) { "independent parameter of the rating curve. " + "Note: This endpoint only works on monotonically increase/decreasing table ratings with " + "a single independent parameter.", - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/ratings/reverse/" // TODO: fix ) @Override public void handle(@NotNull Context ctx) throws Exception { @@ -107,7 +108,7 @@ public void handle(@NotNull Context ctx) throws Exception { RateDao ratingDao = new RateDao(dsl); String office = ctx.pathParam(OFFICE); String ratingId = ctx.pathParam(RATING_ID); - String contentTypeHeader = ctx.req.getContentType(); + String contentTypeHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(contentTypeHeader, RateInputTimeSeries.class); RateInputTimeSeries input = Formats.parseContent(contentType, body, RateInputTimeSeries.class); @@ -120,7 +121,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to reverse rate input values", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rating/ReverseRateValuesController.java b/cwms-data-api/src/main/java/cwms/cda/api/rating/ReverseRateValuesController.java index afbb601f4..176ae5362 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rating/ReverseRateValuesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rating/ReverseRateValuesController.java @@ -46,15 +46,15 @@ import cwms.cda.data.dto.rating.RatedOutputValues; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -97,8 +97,9 @@ public ReverseRateValuesController(MetricRegistry metrics) { "independent parameter of the rating curve. " + "Note: This endpoint only works on monotonically increase/decreasing table ratings with " + "a single independent parameter.", - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/ratings/reverse/rate/value/" // TODO: fix ) @Override public void handle(@NotNull Context ctx) throws Exception { @@ -107,7 +108,7 @@ public void handle(@NotNull Context ctx) throws Exception { RateDao ratingDao = new RateDao(dsl); String office = ctx.pathParam(OFFICE); String ratingId = ctx.pathParam(RATING_ID); - String contentTypeHeader = ctx.req.getContentType(); + String contentTypeHeader = ctx.contentType(); String body = ctx.body(); ContentType contentType = Formats.parseHeader(contentTypeHeader, RateInputValues.class); RateInputValues input = Formats.parseContent(contentType, body, RateInputValues.class); @@ -120,7 +121,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to reverse rate input values", ex); logger.atSevere().withCause(ex).log("Failed to process request to reverse rate input values"); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/rss/RssHandler.java b/cwms-data-api/src/main/java/cwms/cda/api/rss/RssHandler.java index 08671089a..d39b4302b 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/rss/RssHandler.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/rss/RssHandler.java @@ -40,22 +40,20 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import cwms.cda.helpers.ReplaceUtils; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.http.HttpCode; +import io.javalin.http.HttpStatus; import io.javalin.http.HttpResponseException; -import io.javalin.http.util.NaiveRateLimit; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.net.URISyntaxException; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.Instant; -import java.util.concurrent.TimeUnit; import java.util.function.UnaryOperator; import javax.servlet.http.HttpServletResponse; import org.apache.http.client.utils.URIBuilder; @@ -107,7 +105,8 @@ public RssHandler(MetricRegistry metrics) { @OpenApiResponse(status = STATUS_429, description = "Rate Limit exceeded.") }, description = "Returns RSS feed items limited to the last week. End point is limited to 1 request per 10 seconds per client per feed.", - tags = {TAG} + tags = {TAG}, + path = "/rss/{" + OFFICE + "}/{" + NAME + "}" ) @Override public void handle(@NotNull Context ctx) throws Exception { @@ -116,7 +115,7 @@ public void handle(@NotNull Context ctx) throws Exception { ctx.header("Retry-After", "10") .header("RateLimit-Policy", "\"default\";q=6;w=60"); // Limit is 1 request per 10 seconds, or 6 a minute. - NaiveRateLimit.requestPerTimeUnit(ctx, 6, TimeUnit.MINUTES); + //NaiveRateLimit.requestPerTimeUnit(ctx, 6, TimeUnit.MINUTES); // TODO: moves to config using RelateLimitPlugin DSLContext dsl = getDslContext(ctx); String office = ctx.pathParam(OFFICE).toUpperCase(); @@ -127,7 +126,7 @@ public void handle(@NotNull Context ctx) throws Exception { StandardCharsets.UTF_8); if (!CwmsDTOPaginated.CURSOR_CHECK.invoke(cursor)) { ctx.json(new CdaError("cursor or page passed in but failed validation")) - .status(HttpCode.BAD_REQUEST); + .status(HttpStatus.BAD_REQUEST); return; } Instant since = queryParamAsInstant(ctx, SINCE); @@ -141,8 +140,9 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (HttpResponseException ex) { + // TODO: this may need to move as the rate limiting will happen before this code would be called. // an exception to our error handling rules. HttpResponseException, includes multiple other exception // and we don't want to deal with trying to distinguish in ApiServlet. For the time being this logic will // remain here. diff --git a/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesController.java b/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesController.java index b82c7c8ef..119b4bb09 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesController.java @@ -44,7 +44,7 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import cwms.cda.helpers.ReplaceUtils; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import java.io.IOException; import java.net.URISyntaxException; @@ -120,7 +120,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (URISyntaxException | IOException ex) { CdaError re = ExceptionTraceSupport.buildError(ctx, "Failed to process request: " + ex.getLocalizedMessage(), ex); @@ -140,10 +140,10 @@ public void create(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(Controllers.CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, TextTimeSeries.class); - TextTimeSeries tts = Formats.parseContent(contentType, ctx.bodyAsInputStream(), TextTimeSeries.class); + TextTimeSeries tts = Formats.parseContent(contentType, ctx.bodyInputStream(), TextTimeSeries.class); TimeSeriesTextDao dao = getDao(dsl); boolean replaceAll = ctx.queryParamAsClass(REPLACE_ALL, Boolean.class) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesControllerV1.java b/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesControllerV1.java index 785532f40..080a56fa9 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesControllerV1.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesControllerV1.java @@ -43,12 +43,12 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -87,14 +87,16 @@ protected String getOffice(@NotNull Context ctx) { @OpenApiContent(type = Formats.JSONV2, from = TextTimeSeries.class) } )}, - tags = {TAG} + tags = {TAG}, + path = "/timeseries/text", + versions = "1" ) @Override public void getAll(@NotNull Context ctx) { super.getAll(ctx); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String templateId) { super.getOne(ctx, templateId); @@ -111,8 +113,10 @@ public void getOne(@NotNull Context ctx, @NotNull String templateId) { @OpenApiParam(name = REPLACE_ALL, type = Boolean.class, description = "Whether to " + "replace any and all existing text with the specified text. " + "Default is " + DEFAULT_CREATE_REPLACE_ALL)}, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/timeseries/text", + versions = "1" ) @Override public void create(@NotNull Context ctx) { @@ -135,8 +139,10 @@ public void create(@NotNull Context ctx) { }, required = true ), - method = HttpMethod.PATCH, - tags = {TAG} + methods = HttpMethod.PATCH, + tags = {TAG}, + path = "/timeseries/text/{" + NAME + "}", + versions = "1" ) @Override public void update(@NotNull Context ctx, @NotNull String oldTextTimeSeriesId) { @@ -144,9 +150,9 @@ public void update(@NotNull Context ctx, @NotNull String oldTextTimeSeriesId) { try (Timer.Context ignored = markAndTime(UPDATE)) { boolean replaceAll = ctx.queryParamAsClass(REPLACE_ALL, Boolean.class) .getOrDefault(DEFAULT_UPDATE_REPLACE_ALL); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, TextTimeSeries.class); - TextTimeSeries tts = Formats.parseContent(contentType, ctx.bodyAsInputStream(), TextTimeSeries.class); + TextTimeSeries tts = Formats.parseContent(contentType, ctx.bodyInputStream(), TextTimeSeries.class); DSLContext dsl = getDslContext(ctx); TimeSeriesTextDao dao = getDao(dsl); @@ -178,8 +184,10 @@ public void update(@NotNull Context ctx, @NotNull String oldTextTimeSeriesId) { @OpenApiParam(name = VERSION_DATE, description = "The version date for the time " + "series. If not specified, maximum version date is used.") }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/timeseries/text/{" + NAME + "}", + versions = "1" ) @Override public void delete(@NotNull Context ctx, @NotNull String textTimeSeriesId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesControllerV2.java b/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesControllerV2.java index ea6826f7d..9b8803fb4 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesControllerV2.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesControllerV2.java @@ -45,14 +45,13 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.time.Instant; - -import io.javalin.plugin.openapi.annotations.OpenApiResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -93,14 +92,16 @@ protected String getOffice(@NotNull Context ctx) { @OpenApiContent(type = Formats.JSON, from = TextTimeSeries.class) } )}, - tags = {TAG} + tags = {TAG}, + path = "/timeseries/text", + versions = "2" ) @Override public void getAll(@NotNull Context ctx) { super.getAll(ctx); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String templateId) { super.getOne(ctx, templateId); @@ -117,8 +118,10 @@ public void getOne(@NotNull Context ctx, @NotNull String templateId) { @OpenApiParam(name = REPLACE_ALL, type = Boolean.class, description = "Whether to " + "replace any and all existing text with the specified text for matching entries. " + "Default is " + DEFAULT_CREATE_REPLACE_ALL)}, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/timeseries/text", + versions = "2" ) @Override public void create(@NotNull Context ctx) { @@ -165,8 +168,10 @@ public void create(@NotNull Context ctx) { }, required = true ), - method = HttpMethod.PATCH, - tags = {TAG} + methods = HttpMethod.PATCH, + tags = {TAG}, + path = "/timeseries/text/{" + OFFICE + "}/{" + NAME + "}", + versions = "2" ) @Override public void update(@NotNull Context ctx, @NotNull String tsId) { @@ -178,7 +183,7 @@ public void update(@NotNull Context ctx, @NotNull String tsId) { Instant end = requiredInstant(ctx, END); Instant version = queryParamAsInstant(ctx, VERSION_DATE); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, TextTimeSeries.class); DSLContext dsl = getDslContext(ctx); TimeSeriesTextDao dao = getDao(dsl); @@ -186,7 +191,7 @@ public void update(@NotNull Context ctx, @NotNull String tsId) { TextTimeSeries existing = dao.retrieveFromDao(office, tsId, "*", begin, end, version, Integer.MAX_VALUE, null); TextTimeSeries updated = Formats.parsePatchContent( - contentType, existing, ctx.bodyAsInputStream(), TextTimeSeries.class, mergeStrategy); + contentType, existing, ctx.bodyInputStream(), TextTimeSeries.class, mergeStrategy); dao.update(updated, "*", begin, end, version, false); } } @@ -215,8 +220,10 @@ public void update(@NotNull Context ctx, @NotNull String tsId) { @OpenApiParam(name = VERSION_DATE, description = "The version date for the time " + "series. If not specified, maximum version date is used.") }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/timeseries/text/{" + OFFICE + "}/{" + NAME + "}", + versions = "2" ) @Override public void delete(@NotNull Context ctx, @NotNull String textTimeSeriesId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesValueController.java b/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesValueController.java index 72cac81d2..fcdf82dd8 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesValueController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/texttimeseries/TextTimeSeriesValueController.java @@ -30,12 +30,12 @@ import cwms.cda.api.RangeRequestUtil; import cwms.cda.data.dao.ClobDao; import cwms.cda.data.dao.StreamConsumer; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import org.jooq.DSLContext; import static cwms.cda.api.Controllers.*; @@ -67,7 +67,8 @@ public TextTimeSeriesValueController(MetricRegistry metrics) { @OpenApiContent(from = String.class) } )}, - tags = {TextTimeSeriesController.TAG} + tags = {TextTimeSeriesController.TAG}, + path = "/timeseries/text/value/{" + NAME + "}" ) public void handle(Context ctx) { //Implementation will change with new CWMS schema diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupController.java index f5c6fe19f..6a59f703f 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupController.java @@ -54,9 +54,9 @@ import cwms.cda.data.dto.timeseriesgroup.TimeSeriesGroup; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.http.HttpCode; +import io.javalin.http.HttpStatus; import java.io.IOException; import java.util.HashMap; import java.util.List; @@ -97,7 +97,7 @@ protected void getAll(@NotNull Context ctx, String groupOffice) { if (grps.isEmpty()) { CdaError re = new CdaError("No data found for The provided office"); logger.atInfo().log("%s for request %s", re, ctx.fullUrl()); - ctx.status(HttpCode.NOT_FOUND).json(re); + ctx.status(HttpStatus.NOT_FOUND).json(re); } else { String formatHeader = ctx.header(Header.ACCEPT); ContentType contentType = Formats.parseHeader(formatHeader, TimeSeriesGroup.class); @@ -111,7 +111,7 @@ protected void getAll(@NotNull Context ctx, String groupOffice) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } } catch (IOException ex) { CdaError re = new CdaError("Failure to process request to retrieve time series groups"); @@ -144,7 +144,7 @@ protected void getOne(@NotNull Context ctx, @NotNull String groupId, String grou byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { CdaError re = new CdaError("Unable to find group based on parameters given"); logger.atInfo().log("%s%sfor request %s", re, System.lineSeparator(), ctx.fullUrl()); @@ -158,7 +158,7 @@ protected void getOne(@NotNull Context ctx, @NotNull String groupId, String grou } protected TimeSeriesGroup deserializeGroup(Context ctx) { - ContentType contentType = Formats.parseHeader(ctx.req.getContentType(), TimeSeriesGroup.class); + ContentType contentType = Formats.parseHeader(ctx.contentType(), TimeSeriesGroup.class); return Formats.parseContent(contentType, ctx.body(), TimeSeriesGroup.class); } @@ -193,7 +193,7 @@ public void create(@NotNull Context ctx) { sb.delete(sb.length() - 2, sb.length()); detailsMap.put("missing-time-series", sb.toString()); if (ignoreMissing) { - ctx.status(HttpCode.MULTI_STATUS); + ctx.status(HttpStatus.MULTI_STATUS); } else { ctx.status(HttpServletResponse.SC_BAD_REQUEST); @@ -253,7 +253,7 @@ protected void respondToMissingTimeSeries(Context ctx, List missingTimeS sb.delete(sb.length() - 2, sb.length()); detailsMap.put("missing-timeseries", sb.toString()); if (ignoreMissing) { - ctx.status(HttpCode.MULTI_STATUS); + ctx.status(HttpStatus.MULTI_STATUS); } else { ctx.status(HttpServletResponse.SC_BAD_REQUEST); detailsMap.put("message", diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupControllerV1.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupControllerV1.java index 7a2add53e..a46bc06b0 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupControllerV1.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupControllerV1.java @@ -52,15 +52,13 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.util.List; -import java.util.Map; -import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.Strings; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -95,14 +93,15 @@ public TimeSeriesGroupControllerV1(MetricRegistry metrics) { }, responses = { @OpenApiResponse(status = STATUS_200, - content = {@OpenApiContent(isArray = true, from = - TimeSeriesGroup.class, type = Formats.JSON) + content = {@OpenApiContent(from = TimeSeriesGroup[].class, type = Formats.JSON) }), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " + "inputs provided the timeseries group(s) were not found."), @OpenApiResponse(status = STATUS_501, description = "request format is not " + "implemented")}, description = "Returns CWMS Timeseries Groups Data", - tags = {TAG}) + tags = {TAG}, + path = "/timeseries/groups", + versions = "1") @Override public void getAll(@NotNull Context ctx) { String groupOffice = ctx.queryParam(GROUP_OFFICE_ID); @@ -132,7 +131,10 @@ public void getAll(@NotNull Context ctx) { @OpenApiContent(from = TimeSeriesGroup.class, type = Formats.JSON), }) }, - description = "Retrieves requested timeseries group", tags = {"Timeseries Groups"}) + description = "Retrieves requested timeseries group", + tags = {"Timeseries Groups"}, + path = "/timeseries/group/{" + GROUP_ID + "}", + versions = "1") @Override public void getOne(@NotNull Context ctx, @NotNull String groupId) { String groupOffice = ctx.queryParam(GROUP_OFFICE_ID); @@ -162,8 +164,10 @@ public void getOne(@NotNull Context ctx, @NotNull String groupId) { + "with an empty list." + "Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/timeseries/groups", + versions = "1" ) @Override public void create(@NotNull Context ctx) { @@ -193,14 +197,16 @@ public void create(@NotNull Context ctx) { + "belong to. If the group and/or category belong to the CWMS office, " + "this only identifies the timeseries."), }, - method = HttpMethod.PATCH, - tags = {TAG} + methods = HttpMethod.PATCH, + tags = {TAG}, + path = "/timeseries/groups/{" + GROUP_ID + "}", + versions = "1" ) @Override public void update(@NotNull Context ctx, @NotNull String oldGroupId) { try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); String body = ctx.body(); String office = requiredParam(ctx, OFFICE); ContentType contentType = Formats.parseHeader(formatHeader, TimeSeriesGroup.class); @@ -241,8 +247,10 @@ public void update(@NotNull Context ctx, @NotNull String oldGroupId) { description = "Specifies whether to unassign time series in this group before deleting. " + "Default: false"), }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/timeseries/group/{" + GROUP_ID + "}", + versions = "1" ) @Override public void delete(@NotNull Context ctx, @NotNull String groupId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupControllerV2.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupControllerV2.java index e103de328..b1cd1a6ac 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupControllerV2.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesgroup/TimeSeriesGroupControllerV2.java @@ -55,12 +55,12 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; @@ -108,14 +108,16 @@ public TimeSeriesGroupControllerV2(MetricRegistry metrics) { }, responses = { @OpenApiResponse(status = STATUS_200, - content = {@OpenApiContent(isArray = true, from = - TimeSeriesGroup.class, type = Formats.JSON) + content = {@OpenApiContent(from = TimeSeriesGroup[].class, type = Formats.JSON) }), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " + "inputs provided the timeseries group(s) were not found."), @OpenApiResponse(status = STATUS_501, description = "request format is not " + "implemented")}, description = "Returns CWMS Timeseries Groups Data", - tags = {TAG}) + tags = {TAG}, + path = "/timeseries/group", + versions = "2" + ) @Override public void getAll(@NotNull Context ctx) { String groupOffice = ctx.pathParam(OFFICE); @@ -145,7 +147,11 @@ public void getAll(@NotNull Context ctx) { @OpenApiContent(from = TimeSeriesGroup.class, type = Formats.JSON), }) }, - description = "Retrieves requested timeseries group", tags = {"Timeseries Groups"}) + description = "Retrieves requested timeseries group", + tags = {"Timeseries Groups"}, + path = "/timeseries/group", + versions = "2" + ) @Override public void getOne(@NotNull Context ctx, @NotNull String groupId) { String groupOffice = ctx.pathParam(OFFICE); @@ -180,8 +186,9 @@ public void getOne(@NotNull Context ctx, @NotNull String groupId) { + "with an empty list." + "Default: true") }, - method = HttpMethod.POST, - tags = {TAG} + methods = HttpMethod.POST, + tags = {TAG}, + path = "/timeseries/group/{" + OFFICE +"}" ) @Override public void create(@NotNull Context ctx) { @@ -219,8 +226,11 @@ public void create(@NotNull Context ctx) { + "are added to the group's existing assignments. Explicit unassignments in the request body " + "are applied after assignments are stored in either case. Default: MERGE") }, - method = HttpMethod.PATCH, - tags = {TAG} + methods = HttpMethod.PATCH, + tags = {TAG}, + path = "/timeseries/group/{" + OFFICE + "}/{" + GROUP_ID + "}", + versions = "2" + ) @Override public void update(@NotNull Context ctx, @NotNull String oldGroupId) { @@ -228,7 +238,7 @@ public void update(@NotNull Context ctx, @NotNull String oldGroupId) { DSLContext dsl = getDslContext(ctx); String office = ctx.pathParam(OFFICE); Boolean ignoreNulls = ctx.queryParamAsClass(IGNORE_NULLS, Boolean.class).getOrDefault(true); - ContentType contentType = Formats.parseHeader(ctx.req.getContentType(), TimeSeriesGroupPatch.class); + ContentType contentType = Formats.parseHeader(ctx.contentType(), TimeSeriesGroupPatch.class); TimeSeriesGroupPatch patch = Formats.parseContent(contentType, ctx.body(), TimeSeriesGroupPatch.class); validateOffice(office, patch.getOfficeId()); @@ -357,8 +367,10 @@ private static String key(String office, String tsId) { description = "Specifies whether to unassign time series in this group before deleting. " + "Default: false"), }, - method = HttpMethod.DELETE, - tags = {TAG} + methods = HttpMethod.DELETE, + tags = {TAG}, + path = "/timeseries/group/{" + OFFICE + "}/{" + GROUP_ID + "}", + versions = "2" ) @Override public void delete(@NotNull Context ctx, @NotNull String groupId) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileCatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileCatalogController.java index caae208f6..86d404bca 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileCatalogController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileCatalogController.java @@ -44,14 +44,16 @@ import cwms.cda.data.dto.timeseriesprofile.TimeSeriesProfileList; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -76,9 +78,10 @@ public TimeSeriesProfileCatalogController(MetricRegistry metrics) { @OpenApiParam(name = PAGE, description = "The page cursor. Default is null"), @OpenApiParam(name = PAGE_SIZE, description = "The page size. Default is 500") }, - method = HttpMethod.GET, + methods = HttpMethod.GET, summary = "Get a catalog of time series profiles", tags = {TAG}, + path = "/timeseries/profile/catalog", responses = { @OpenApiResponse(status = STATUS_200, description = "A TimeSeriesProfile object", @@ -110,7 +113,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = results.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve time series profiles", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileController.java index 854a2362d..4969489bb 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileController.java @@ -42,14 +42,14 @@ import cwms.cda.data.dto.timeseriesprofile.TimeSeriesProfile; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -72,9 +72,10 @@ public TimeSeriesProfileController(MetricRegistry metrics) { @OpenApiParam(name = LOCATION_ID, description = "The location ID associated with the " + "time series profile") }, - method = HttpMethod.GET, + methods = HttpMethod.GET, summary = "Get a time series profile", tags = {TAG}, + path = "/timeseries/profile", responses = { @OpenApiResponse(status = STATUS_200, description = "A TimeSeriesProfileParser object", @@ -102,7 +103,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Time Series Profile", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileCreateController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileCreateController.java index bb3f311bd..195fd9a99 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileCreateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileCreateController.java @@ -37,12 +37,12 @@ import cwms.cda.formatters.Formats; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -59,9 +59,10 @@ public TimeSeriesProfileCreateController(MetricRegistry metrics) { @OpenApiParam(name = FAIL_IF_EXISTS, type = boolean.class, description = "If true, the parser will " + "fail to save if the TimeSeriesProfile already exists. Default true."), }, - method = HttpMethod.POST, + methods = HttpMethod.POST, summary = "Create a new time series profile", tags = {TAG}, + path = "/timeseries/profile", requestBody = @OpenApiRequestBody(content = {@OpenApiContent(from = TimeSeriesProfile.class)}), responses = { @OpenApiResponse(status = "400", description = "Invalid input") diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileDeleteController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileDeleteController.java index 04d8a4803..9009e1f36 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileDeleteController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileDeleteController.java @@ -42,10 +42,10 @@ import cwms.cda.data.dao.timeseriesprofile.TimeSeriesProfileDao; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -68,9 +68,10 @@ public TimeSeriesProfileDeleteController(MetricRegistry metrics) { @OpenApiParam(name = PARAMETER_ID, description = "The key parameter associated with the " + "time series profile") }, - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, summary = "Delete a time series profile", tags = {TAG}, + path = "/timeseries/profile/instance", // TODO: path params responses = { @OpenApiResponse(status = STATUS_400, description = "Invalid input"), @OpenApiResponse(status = STATUS_204, description = "Time series profile deleted"), diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceCatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceCatalogController.java index 903ac6a1f..d39c4d95a 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceCatalogController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceCatalogController.java @@ -43,14 +43,16 @@ import cwms.cda.data.dto.timeseriesprofile.TimeSeriesProfileInstance; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -75,11 +77,12 @@ public TimeSeriesProfileInstanceCatalogController(MetricRegistry metrics) { @OpenApiParam(name = VERSION_MASK, description = "The version mask of the" + " time series profile instance. Default is *"), }, - method = HttpMethod.GET, + methods = HttpMethod.GET, summary = "Get all time series profile instances that match the provided masks. This endpoint will return a " + "list of time series profile instances without the associated data. Data for an instance can be " + "retrieved using the singular retrieval endpoint.", tags = {TAG}, + path = "/timeseries/profiles/instance/catalog", responses = { @OpenApiResponse(status = STATUS_200, description = "A TimeSeriesProfileInstance object", @@ -109,7 +112,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve time series profile instances", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceController.java index b52b2f3ca..15397693e 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceController.java @@ -59,14 +59,14 @@ import cwms.cda.data.dto.timeseriesprofile.TimeSeriesProfileInstance; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.time.Instant; import java.util.Arrays; @@ -126,7 +126,8 @@ public TimeSeriesProfileInstanceController(MetricRegistry metrics) { @OpenApiParam(name = VERSION, description = "The version of the" + " time series profile instance.", required = true), }, - method = HttpMethod.GET, + methods = HttpMethod.GET, + path = "/timeseries/profile/instance", // TOOD: path parameters summary = "Get a time series profile instance that matches the provided parameters.", tags = {TAG}, responses = { @@ -175,7 +176,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve time series profile instance", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceCreateController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceCreateController.java index 2f7682a34..b8b7243f6 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceCreateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceCreateController.java @@ -38,12 +38,12 @@ import cwms.cda.helpers.annotations.IgnoreRequiredQueryParamMismatch; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.time.Instant; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -73,9 +73,10 @@ public TimeSeriesProfileInstanceCreateController(MetricRegistry metrics) { @OpenApiParam(name = VERSION, description = "The version of the" + " time series profile instance.", required = true), }, - method = HttpMethod.POST, + methods = HttpMethod.POST, summary = "Create a new time series profile instance by parsing provided data", tags = {TAG}, + path = "/timeseries/profile/instance", requestBody = @OpenApiRequestBody(content = {@OpenApiContent(from = TimeSeriesProfile.class)}), responses = { @OpenApiResponse(status = "201", description = "Time series profile instance created"), diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceDeleteController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceDeleteController.java index 3e21dc8da..bd91b4b58 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceDeleteController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileInstanceDeleteController.java @@ -45,10 +45,10 @@ import cwms.cda.data.dto.CwmsId; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.time.Instant; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -83,12 +83,13 @@ public TimeSeriesProfileInstanceDeleteController(MetricRegistry metrics) { @OpenApiParam(name = VERSION, description = "The version of the" + " time series profile instance.", required = true), }, - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, summary = "Delete a time series profile instance", tags = {TAG}, responses = { @OpenApiResponse(status = "400", description = "Invalid input") - } + }, + path = "/timeseries/profiles" ) @Override public void handle(@NotNull Context ctx) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserCatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserCatalogController.java index 757521274..d6a9e3c8d 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserCatalogController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserCatalogController.java @@ -42,14 +42,14 @@ import cwms.cda.data.dto.timeseriesprofile.TimeSeriesProfileParser; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -76,17 +76,18 @@ public TimeSeriesProfileParserCatalogController(MetricRegistry metrics) { @OpenApiResponse(status = STATUS_200, description = "A TimeSeriesProfileParser object", content = { - @OpenApiContent(isArray = true, from = TimeSeriesProfileParser.class, type = Formats.JSONV1), - @OpenApiContent(isArray = true, from = TimeSeriesProfileParser.class, type = Formats.JSON) + @OpenApiContent(from = TimeSeriesProfileParser[].class, type = Formats.JSONV1), + @OpenApiContent(from = TimeSeriesProfileParser[].class, type = Formats.JSON) }), @OpenApiResponse(status = STATUS_404, description = "The provided combination of parameters did not" + " find a TimeSeriesProfileParser object"), @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.GET, + methods = HttpMethod.GET, summary = "Retrieve a list of TimeSeries Profile Parsers that match the provided mask parameters", - tags = {TAG} + tags = {TAG}, + path = "/timeseries/profile/catalog" ) @Override public void handle(@NotNull Context ctx) { @@ -108,7 +109,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve time series profile parsers", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserController.java index 53bc6165b..269b8d8aa 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserController.java @@ -44,14 +44,14 @@ import cwms.cda.data.dto.timeseriesprofile.TimeSeriesProfileParser; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -87,9 +87,10 @@ public TimeSeriesProfileParserController(MetricRegistry metrics) { + "implemented") }, - method = HttpMethod.GET, + methods = HttpMethod.GET, summary = "Get a TimeSeriesProfile Parser by ID", - tags = {TAG} + tags = {TAG}, + path = "/timeseries/profile" ) @Override @@ -110,7 +111,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve time series profile parser", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserCreateController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserCreateController.java index 42baab219..18caf8d13 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserCreateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserCreateController.java @@ -36,14 +36,14 @@ import cwms.cda.data.dto.timeseriesprofile.TimeSeriesProfileParserColumnar; import cwms.cda.data.dto.timeseriesprofile.TimeSeriesProfileParserIndexed; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -67,9 +67,10 @@ public TimeSeriesProfileParserCreateController(MetricRegistry metrics) { }, required = true ), - method = HttpMethod.POST, + methods = HttpMethod.POST, summary = "Store a TimeSeriesProfile Parser", - tags = {TAG} + tags = {TAG}, + path = "/timeseries/profile" ) @Override public void handle(@NotNull Context ctx) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserDeleteController.java b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserDeleteController.java index 554f4aac8..509402a46 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserDeleteController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/timeseriesprofile/TimeSeriesProfileParserDeleteController.java @@ -41,10 +41,13 @@ import cwms.cda.data.dao.timeseriesprofile.TimeSeriesProfileParserDao; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -73,9 +76,10 @@ public TimeSeriesProfileParserDeleteController(MetricRegistry metrics) { + " TimeSeriesProfileParser object"), @OpenApiResponse(status = STATUS_501, description = "Requested format is not implemented") }, - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, summary = "Delete a TimeSeriesProfile Parser by ID", - tags = {TAG} + tags = {TAG}, + path = "/timeseries/profile" ) @Override public void handle(@NotNull Context ctx) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCatalogController.java index ce899b226..26b41b061 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCatalogController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCatalogController.java @@ -61,14 +61,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import cwms.cda.helpers.annotations.IgnoreRequiredQueryParamMismatch; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.time.Instant; import java.util.List; @@ -132,10 +132,8 @@ protected WaterSupplyAccountingDao getWaterSupplyAccountingDao(DSLContext dsl) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(from = WaterSupplyAccounting.class, isArray = true, - type = Formats.JSONV1), - @OpenApiContent(from = WaterSupplyAccounting.class, isArray = true, - type = Formats.JSON) + @OpenApiContent(from = WaterSupplyAccounting[].class, type = Formats.JSONV1), + @OpenApiContent(from = WaterSupplyAccounting[].class, type = Formats.JSON) }), @OpenApiResponse(status = STATUS_404, description = "Pump Accounting not found for " + "provided input parameters."), @@ -149,7 +147,7 @@ protected WaterSupplyAccountingDao getWaterSupplyAccountingDao(DSLContext dsl) { }, description = "Get pump accounting entries associated with a water supply contract.", path = "/projects/{office}/water-user/{water-user}/contracts/{contract-name}/accounting", - method = HttpMethod.GET, + methods = HttpMethod.GET, tags = {TAG} ) @IgnoreRequiredQueryParamMismatch(parameterNames = {TIMEZONE}) @@ -219,7 +217,7 @@ public void handle(Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve pump accounting", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCreateController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCreateController.java index a381517fa..fdca2fa55 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCreateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCreateController.java @@ -47,17 +47,15 @@ import cwms.cda.data.dto.watersupply.WaterSupplyAccounting; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import java.nio.charset.StandardCharsets; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.time.Instant; -import java.util.Arrays; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; @@ -105,7 +103,7 @@ protected WaterSupplyAccountingDao getWaterSupplyAccountingDao(DSLContext dsl) { }, description = "Create a new pump accounting entry associated with a water supply contract.", path = "/projects/{office}/water-user/{water-user}/contracts/{contract-name}/accounting", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAG} ) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractCatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractCatalogController.java index 91b27203c..21446cbe7 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractCatalogController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractCatalogController.java @@ -42,13 +42,13 @@ import cwms.cda.data.dto.watersupply.WaterUserContract; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -83,7 +83,7 @@ public WaterContractCatalogController(MetricRegistry metrics) { }, description = "Return all water contracts", path = "/projects/{office}/{project-id}/water-users/{water-user}/contracts", - method = HttpMethod.GET, + methods = HttpMethod.GET, tags = {TAG} ) @Override @@ -104,7 +104,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve water contracts", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractController.java index ea5bb35a2..dad720e55 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractController.java @@ -43,14 +43,14 @@ import cwms.cda.data.dto.watersupply.WaterUserContract; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -88,7 +88,7 @@ public WaterContractController(MetricRegistry metrics) { }, description = "Return a specified water contract", path = "/projects/{office}/{project-id}/water-user/{water-user}/contracts/{contract-name}", - method = HttpMethod.GET, + methods = HttpMethod.GET, tags = {TAG} ) @@ -111,7 +111,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve water contract", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractCreateController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractCreateController.java index 69b22dbaf..81224c452 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractCreateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractCreateController.java @@ -44,13 +44,12 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -87,7 +86,7 @@ public WaterContractCreateController(MetricRegistry metrics) { required = true) }, description = "Create a new water contract", - method = HttpMethod.POST, + methods = HttpMethod.POST, path = "/projects/{office}/{project-id}/water-user/{water-user}/contracts", tags = {TAG} ) @@ -98,7 +97,7 @@ public void handle(@NotNull Context ctx) { logUnusedPathParameter(ctx, OFFICE, "Body contains required information."); try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, WaterUserContract.class); ctx.contentType(contentType.toString()); WaterUserContract waterContract = Formats.parseContent(contentType, ctx.body(), WaterUserContract.class); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractDeleteController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractDeleteController.java index 6e967d45c..71aa806b5 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractDeleteController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractDeleteController.java @@ -43,9 +43,9 @@ import cwms.cda.data.dto.StatusResponse; import cwms.cda.data.dto.watersupply.WaterUserContract; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -72,7 +72,7 @@ public WaterContractDeleteController(MetricRegistry metrics) { }, description = "Delete a specified water contract", path = "/projects/{office}/{project-id}/water-users/{water-user}/contracts/{contract-name}", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, tags = {TAG} ) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeCatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeCatalogController.java index 496018ff3..576efe90a 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeCatalogController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeCatalogController.java @@ -38,14 +38,14 @@ import cwms.cda.data.dto.LookupType; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -78,7 +78,7 @@ public WaterContractTypeCatalogController(MetricRegistry metrics) { }, description = "Get all water contract types", path = "/projects/contracts/{office}/contract-types", - method = HttpMethod.GET, + methods = HttpMethod.GET, tags = {TAG} ) @@ -98,7 +98,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve water contract types", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeCreateController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeCreateController.java index 003375014..b99724476 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeCreateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeCreateController.java @@ -38,13 +38,12 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -71,7 +70,7 @@ public WaterContractTypeCreateController(MetricRegistry metrics) { @OpenApiResponse(status = "501", description = "Requested format is not implemented.") }, description = "Create a new water contract type", - method = HttpMethod.POST, + methods = HttpMethod.POST, path = "/projects/{office}/contract-types", tags = {TAG} ) @@ -81,7 +80,7 @@ public void handle(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); boolean failIfExists = ctx.queryParamAsClass(FAIL_IF_EXISTS, Boolean.class).getOrDefault(true); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, LookupType.class); ctx.contentType(contentType.toString()); LookupType contractType = Formats.parseContent(contentType, ctx.body(), LookupType.class); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeDeleteController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeDeleteController.java index 1ccf26aa4..cf255c72a 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeDeleteController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractTypeDeleteController.java @@ -38,10 +38,9 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -63,7 +62,7 @@ public WaterContractTypeDeleteController(MetricRegistry metrics) { + "the contract type to delete"), }, description = "Delete a water contract type", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, path = "/projects/{office}/contract-types/{display-value}", tags = {TAG} ) @@ -74,7 +73,7 @@ public void handle(@NotNull Context ctx) { DSLContext dsl = getDslContext(ctx); String office = ctx.pathParam(OFFICE); String displayValue = ctx.pathParam(DISPLAY_VALUE); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, LookupType.class); ctx.contentType(contentType.toString()); WaterContractDao dao = new WaterContractDao(dsl); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractUpdateController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractUpdateController.java index d7faded49..3cebe4041 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractUpdateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterContractUpdateController.java @@ -42,15 +42,13 @@ import cwms.cda.data.dto.watersupply.WaterUserContract; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; import io.javalin.http.Context; -import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -89,7 +87,7 @@ public WaterContractUpdateController(MetricRegistry metrics) { @OpenApiResponse(status = "501", description = "Requested format is not implemented.") }, description = "Renames a water contract", - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, path = "/projects/{office}/{project-id}/water-users/{water-user}/contracts/{contract-name}", tags = {TAG} ) @@ -103,7 +101,7 @@ public void handle(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(UPDATE)) { DSLContext dsl = getDslContext(ctx); String contractName = ctx.pathParam(CONTRACT_NAME); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, WaterUserContract.class); ctx.contentType(contentType.toString()); String newName = requiredParam(ctx, CONTRACT_NAME); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterPumpDisassociateController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterPumpDisassociateController.java index 1c1dffc2f..6f96a8443 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterPumpDisassociateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterPumpDisassociateController.java @@ -41,12 +41,10 @@ import cwms.cda.data.dto.CwmsId; import cwms.cda.data.dto.watersupply.PumpType; import cwms.cda.data.dto.watersupply.WaterUserContract; -import io.javalin.core.validation.JavalinValidation; import io.javalin.http.Context; -import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -80,7 +78,7 @@ public WaterPumpDisassociateController(MetricRegistry metrics) { }, description = "Disassociate a pump from a contract", path = "/projects/{office}/{project-id}/water-user/{water-user}/contracts/{contract-name}/pumps/{name}", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, tags = {TAG} ) @@ -93,7 +91,7 @@ public void handle(@NotNull Context ctx) { String pumpName = ctx.pathParam(NAME); String projectName = ctx.pathParam(PROJECT_ID); String entityName = ctx.pathParam(WATER_USER); - JavalinValidation.register(PumpType.class, PumpType::valueOf); + //JavalinValidation.register(PumpType.class, PumpType::valueOf); // TODO: move to config PumpType pumpType = requiredParamAs(ctx, PUMP_TYPE, PumpType.class); String contractName = ctx.pathParam(CONTRACT_NAME); WaterContractDao contractDao = getContractDao(dsl); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserCatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserCatalogController.java index 353b43c6b..3781f2e6b 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserCatalogController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserCatalogController.java @@ -42,14 +42,14 @@ import cwms.cda.data.dto.watersupply.WaterUserContract; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -80,7 +80,7 @@ public WaterUserCatalogController(MetricRegistry metrics) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "Gets all water users.", - method = HttpMethod.GET, + methods = HttpMethod.GET, path = "/projects/{office}/{project-id}/water-user/all-users", tags = {TAG} ) @@ -102,7 +102,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve water users", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserController.java index 3c9bfbc4d..88273cc20 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserController.java @@ -43,14 +43,14 @@ import cwms.cda.data.dto.watersupply.WaterUserContract; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -82,7 +82,7 @@ public WaterUserController(MetricRegistry metrics) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "Gets a specified water user.", - method = HttpMethod.GET, + methods = HttpMethod.GET, path = "/projects/{office}/{project-id}/water-user/{water-user}", tags = {TAG} ) @@ -105,7 +105,7 @@ public void handle(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve water user", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserCreateController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserCreateController.java index cfa0c8089..f2d1bfc9e 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserCreateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserCreateController.java @@ -37,12 +37,12 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -69,7 +69,7 @@ public WaterUserCreateController(MetricRegistry metrics) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not implemented") }, description = "Stores a water user to CWMS.", - method = HttpMethod.POST, + methods = HttpMethod.POST, path = "/projects/{office}/{project-id}/water-user", tags = {TAG} ) @@ -77,7 +77,7 @@ public WaterUserCreateController(MetricRegistry metrics) { public void handle(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, WaterUser.class); ctx.contentType(contentType.toString()); WaterUser user = Formats.parseContent(contentType, ctx.body(), WaterUser.class); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserDeleteController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserDeleteController.java index 235ebf686..9b2403727 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserDeleteController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserDeleteController.java @@ -41,9 +41,9 @@ import cwms.cda.data.dto.CwmsId; import cwms.cda.data.dto.StatusResponse; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -70,7 +70,7 @@ public WaterUserDeleteController(MetricRegistry metrics) { required = true) }, description = "Deletes a water user from CWMS.", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, path = "/projects/{office}/{project-id}/water-user/{water-user}", tags = {TAG} ) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserUpdateController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserUpdateController.java index 1f69eff36..aa5f30643 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserUpdateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/WaterUserUpdateController.java @@ -44,15 +44,13 @@ import cwms.cda.data.dto.watersupply.WaterUser; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; import io.javalin.http.Context; -import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -87,7 +85,7 @@ public WaterUserUpdateController(MetricRegistry metrics) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not implemented") }, description = "Updates a water user in CWMS.", - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, path = "/projects/{office}/{project-id}/water-user/{water-user}", tags = {TAG} ) @@ -95,7 +93,7 @@ public WaterUserUpdateController(MetricRegistry metrics) { public void handle(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(UPDATE)) { DSLContext dsl = getDslContext(ctx); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, WaterUser.class); ctx.contentType(contentType.toString()); String newName = requiredParam(ctx, NAME); From 30736b6489d8c20c3da5bac6ebe3df2401e6bad6 Mon Sep 17 00:00:00 2001 From: "Michael A. Neilson" Date: Wed, 30 Sep 2026 21:00:23 +0000 Subject: [PATCH 07/69] Batch of controllers. --- .../kind/GateChangeCreateController.java | 21 ++++----- .../kind/GateChangeDeleteController.java | 15 ++++--- .../kind/GateChangeGetAllController.java | 19 ++++---- .../cda/api/location/kind/LockController.java | 43 +++++++++++-------- .../api/location/kind/OutletController.java | 39 +++++++++-------- .../kind/VirtualOutletController.java | 33 +++++++------- .../kind/VirtualOutletCreateController.java | 17 ++++---- .../api/project/LockRevokerRightsCatalog.java | 20 ++++----- .../project/ProjectChildLocationHandler.java | 18 ++++---- .../cda/api/project/ProjectLockCatalog.java | 7 ++- .../cda/api/project/ProjectLockCatalogV1.java | 15 ++++--- .../cda/api/project/ProjectLockCatalogV2.java | 15 ++++--- .../cda/api/project/ProjectLockGetOne.java | 4 +- .../cda/api/project/ProjectLockGetOneV1.java | 16 ++++--- .../cda/api/project/ProjectLockGetOneV2.java | 16 ++++--- .../cda/api/project/ProjectLockReleaseV1.java | 11 ++--- .../cda/api/project/ProjectLockReleaseV2.java | 11 ++--- .../cda/api/project/ProjectLockRequest.java | 2 +- .../cda/api/project/ProjectLockRequestV1.java | 21 ++++----- .../cda/api/project/ProjectLockRequestV2.java | 21 ++++----- .../api/project/ProjectLockRevokeDenyV1.java | 11 ++--- .../api/project/ProjectLockRevokeDenyV2.java | 11 ++--- .../cda/api/project/ProjectLockRevokeV1.java | 15 ++++--- .../cda/api/project/ProjectLockRevokeV2.java | 11 ++--- .../project/ProjectPublishStatusUpdate.java | 19 ++++---- .../project/RemoveAllLockRevokerRights.java | 8 ++-- .../api/project/UpdateLockRevokerRights.java | 9 ++-- 27 files changed, 242 insertions(+), 206 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeCreateController.java b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeCreateController.java index 05f132965..e80eddeba 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeCreateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeCreateController.java @@ -28,14 +28,14 @@ import cwms.cda.data.dto.location.kind.GateChange; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -52,8 +52,8 @@ public GateChangeCreateController(MetricRegistry metrics) { @OpenApi( requestBody = @OpenApiRequestBody( content = { - @OpenApiContent(from = GateChange.class, isArray = true, type = Formats.JSONV1), - @OpenApiContent(from = GateChange.class, isArray = true, type = Formats.JSON) + @OpenApiContent(from = GateChange[].class, type = Formats.JSONV1), + @OpenApiContent(from = GateChange[].class, type = Formats.JSON) }, required = true), queryParams = { @@ -66,8 +66,9 @@ public GateChangeCreateController(MetricRegistry metrics) { + " Deprecated, use " + OVERRIDE_PROTECTION) }, description = "Create CWMS Gate Changes", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {OutletController.TAG}, + path = "/gate/changes", // TODO: fix responses = { @OpenApiResponse(status = STATUS_201, description = "Gate Changes successfully stored to CWMS.") } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeDeleteController.java b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeDeleteController.java index b8c793e32..29ecc7d0c 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeDeleteController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeDeleteController.java @@ -30,12 +30,12 @@ import cwms.cda.data.dto.CwmsId; import cwms.cda.helpers.annotations.IgnoreRequiredQueryParamMismatch; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.time.Instant; -import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -68,7 +68,8 @@ public GateChangeDeleteController(MetricRegistry metrics) { + "inputs provided the project was not found.")}, description = "Deletes matching CWMS gate change data for a Reservoir Project.", tags = {OutletController.TAG}, - method = HttpMethod.DELETE + methods = HttpMethod.DELETE, + path = "/gate/change" // TODO: fix ) @IgnoreRequiredQueryParamMismatch(parameterNames = {TIMEZONE}) @Override @@ -83,7 +84,7 @@ public void handle(@NotNull Context context) throws Exception { DSLContext dsl = JooqDao.getDslContext(context); OutletDao dao = new OutletDao(dsl); dao.deleteOperationalChanges(projectId, startTime, endTime, overrideProtection); - context.res.setStatus(HttpServletResponse.SC_NO_CONTENT); + context.status(HttpStatus.NO_CONTENT); } } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeGetAllController.java b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeGetAllController.java index 57a58f814..428f9b249 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeGetAllController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/GateChangeGetAllController.java @@ -47,12 +47,12 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import cwms.cda.helpers.annotations.IgnoreRequiredQueryParamMismatch; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.time.Instant; import java.util.List; @@ -104,12 +104,13 @@ public GateChangeGetAllController(MetricRegistry metrics) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(from = GateChange.class, isArray = true, type = Formats.JSONV1), - @OpenApiContent(from = GateChange.class, isArray = true, type = Formats.JSON), + @OpenApiContent(from = GateChange[].class, type = Formats.JSONV1), + @OpenApiContent(from = GateChange[].class, type = Formats.JSON), }) }, description = "Returns matching CWMS gate change data for a Reservoir Project.", - tags = {OutletController.TAG} + tags = {OutletController.TAG}, + path = "/gates-chage/" // TODO: check ) @IgnoreRequiredQueryParamMismatch(parameterNames = {TIMEZONE}) @Override @@ -138,7 +139,7 @@ public void handle(@NotNull Context context) { byte[] bytes = serialized.getBytes(); context.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - context.res.getOutputStream().write(bytes); + context.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(context, "Failed to process request to retrieve Gate Changes", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/LockController.java b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/LockController.java index d72574cf6..a4ea282a7 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/LockController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/LockController.java @@ -60,14 +60,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -102,12 +102,13 @@ private Timer.Context markAndTime(String subject) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = Lock.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = Lock.class) + @OpenApiContent(type = Formats.JSONV1, from = Lock[].class), + @OpenApiContent(type = Formats.JSON, from = Lock[].class) }) }, description = "Returns matching CWMS Lock Data for a Reservoir Project.", - tags = {TAG} + tags = {TAG}, + path = "/locks" ) @Override public void getAll(@NotNull Context ctx) { @@ -128,7 +129,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, ERROR_MSG, ex); LOGGER.atSevere().withCause(ex).log(ERROR_MSG); @@ -150,12 +151,13 @@ public void getAll(@NotNull Context ctx) { responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(isArray = true, type = Formats.JSONV1, from = Lock.class), - @OpenApiContent(isArray = true, type = Formats.JSON, from = Lock.class) + @OpenApiContent(type = Formats.JSONV1, from = Lock[].class), + @OpenApiContent(type = Formats.JSON, from = Lock[].class) }) }, description = "Returns CWMS Lock Data", - tags = {TAG} + tags = {TAG}, + path = "/locks/{" + NAME + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String name) { @@ -180,7 +182,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, ERROR_MSG, ex); LOGGER.atSevere().withCause(ex).log(ERROR_MSG); @@ -199,8 +201,9 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { description = "Create will fail if provided ID already exists. Default: true") }, description = "Create CWMS Lock", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAG}, + path = "/locks", responses = { @OpenApiResponse(status = STATUS_201, description = "Lock successfully stored to CWMS.") } @@ -208,7 +211,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @Override public void create(Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String acceptHeader = ctx.req.getContentType(); + String acceptHeader = ctx.contentType(); String formatHeader = acceptHeader != null ? acceptHeader : Formats.JSONV1; ContentType contentType = Formats.parseHeader(formatHeader, Lock.class); Lock lock = Formats.parseContent(contentType, ctx.body(), Lock.class); @@ -240,8 +243,9 @@ public void create(Context ctx) { @OpenApiParam(name = NAME, required = true, description = "Specifies the new lock name.") }, description = "Rename CWMS Lock", - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, tags = {TAG}, + path = "/locks/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Lock successfully renamed in CWMS.") } @@ -271,8 +275,9 @@ public void update(@NotNull Context ctx, @NotNull String name) { + "Defaults to \"DELETE_KEY\"", type = JooqDao.DeleteMethod.class) }, description = "Delete CWMS Lock", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, tags = {TAG}, + path = "/locks/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Lock successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " diff --git a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/OutletController.java b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/OutletController.java index 3609a7ab0..a36bc7828 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/OutletController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/OutletController.java @@ -48,14 +48,14 @@ import cwms.cda.data.dto.location.kind.Outlet; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -83,8 +83,9 @@ public OutletController(MetricRegistry metrics) { description = "Create will fail if provided ID already exists. Default: true") }, description = "Create CWMS Outlet", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAG}, + path = "/outlets", responses = { @OpenApiResponse(status = STATUS_201, description = "Outlet successfully stored to CWMS.") } @@ -92,7 +93,7 @@ public OutletController(MetricRegistry metrics) { @Override public void create(@NotNull Context ctx) { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, Outlet.class); Outlet outlet = Formats.parseContent(contentType, ctx.body(), Outlet.class); outlet.validate(); @@ -115,12 +116,13 @@ public void create(@NotNull Context ctx) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(from = Outlet.class, isArray = true, type = Formats.JSONV1), - @OpenApiContent(from = Outlet.class, isArray = true, type = Formats.JSON) + @OpenApiContent(from = Outlet[].class, type = Formats.JSONV1), + @OpenApiContent(from = Outlet[].class, type = Formats.JSON) }) }, description = "Returns matching CWMS Outlet Data for a Reservoir Project.", - tags = {TAG} + tags = {TAG}, + path = "/outlets" ) @Override public void getAll(@NotNull Context ctx) { @@ -139,7 +141,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve outlets", ex); logger.atSevere().withCause(ex).log("Failed to process request to retrieve outlets"); @@ -164,7 +166,8 @@ public void getAll(@NotNull Context ctx) { }) }, description = "Returns CWMS Outlet Data", - tags = {TAG} + tags = {TAG}, + path = "/outlets/{" + NAME + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String name) { @@ -182,7 +185,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve outlet", ex); logger.atSevere().withCause(ex).log("Failed to process request to retrieve outlet"); @@ -201,8 +204,9 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @OpenApiParam(name = NAME, required = true, description = "Specifies the new outlet location-id."), }, description = "Rename CWMS Outlet", - method = HttpMethod.PATCH, + methods = HttpMethod.PATCH, tags = {TAG}, + path = "/outlets/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "CWMS Outlet successfully renamed.") } @@ -232,8 +236,9 @@ public void update(@NotNull Context ctx, @NotNull String name) { + "Defaults to \"DELETE_KEY\"", type = JooqDao.DeleteMethod.class) }, description = "Delete CWMS Outlet", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, tags = {TAG}, + path = "/outlets/{" + NAME + "}", responses = { @OpenApiResponse(status = STATUS_200, description = "Outlet successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " diff --git a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/VirtualOutletController.java b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/VirtualOutletController.java index edc0b2863..79ac5c6d9 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/VirtualOutletController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/VirtualOutletController.java @@ -42,13 +42,13 @@ import cwms.cda.data.dto.location.kind.VirtualOutlet; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -62,7 +62,7 @@ public VirtualOutletController(MetricRegistry metrics) { super(metrics); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(@NotNull Context ctx) { //Implemented in VirtualOutletCreateController @@ -78,12 +78,13 @@ public void create(@NotNull Context ctx) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(from = VirtualOutlet.class, isArray = true, type = Formats.JSONV1), - @OpenApiContent(from = VirtualOutlet.class, isArray = true, type = Formats.JSON) + @OpenApiContent(from = VirtualOutlet[].class, type = Formats.JSONV1), + @OpenApiContent(from = VirtualOutlet[].class, type = Formats.JSON) }) }, description = "Returns matching CWMS Virtual Outlet Data for a Reservoir Project.", - tags = {OutletController.TAG} + tags = {OutletController.TAG}, + path = "/outlet/virtual" // TODO: fix ) @Override public void getAll(@NotNull Context ctx) { @@ -102,7 +103,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Virtual Outlets", ex); @@ -128,7 +129,8 @@ public void getAll(@NotNull Context ctx) { }) }, description = "Returns CWMS Virtual Outlet Data", - tags = {OutletController.TAG} + tags = {OutletController.TAG}, + path = "/outlets/virtual/{" // TODO: implement ) @Override public void getOne(@NotNull Context ctx, @NotNull String name) { @@ -147,7 +149,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { byte[] bytes = serialized.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Virtual Outlet", ex); @@ -156,7 +158,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { } } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context ctx, @NotNull String s) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -177,8 +179,9 @@ public void update(@NotNull Context ctx, @NotNull String s) { type = JooqDao.DeleteMethod.class) }, description = "Delete CWMS Virtual Outlet", - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, tags = {OutletController.TAG}, + path = "/outlet/virtual/{", // TODO: fix responses = { @OpenApiResponse(status = STATUS_200, description = "Virtual Outlet successfully deleted from CWMS."), @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " diff --git a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/VirtualOutletCreateController.java b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/VirtualOutletCreateController.java index b6d3e8557..dd90691e3 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/location/kind/VirtualOutletCreateController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/location/kind/VirtualOutletCreateController.java @@ -29,12 +29,12 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -59,8 +59,9 @@ public VirtualOutletCreateController(MetricRegistry metrics) { description = "Create will fail if provided ID already exists. Default: true"), }, description = "Create CWMS Virtual Outlet", - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {OutletController.TAG}, + path = "/outlets/virtual", // TODO: fix responses = { @OpenApiResponse(status = STATUS_204, description = "Virtual Outlet successfully stored to CWMS.") } @@ -68,7 +69,7 @@ public VirtualOutletCreateController(MetricRegistry metrics) { @Override public void handle(@NotNull Context ctx) throws Exception { try (Timer.Context ignored = markAndTime(CREATE)) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, VirtualOutlet.class); VirtualOutlet virtualOutlet = Formats.parseContent(contentType, ctx.body(), VirtualOutlet.class); boolean failIfExists = queryParamAsClass(ctx, Boolean.class, true, FAIL_IF_EXISTS); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/LockRevokerRightsCatalog.java b/cwms-data-api/src/main/java/cwms/cda/api/project/LockRevokerRightsCatalog.java index 811aa8dd5..da50f530b 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/LockRevokerRightsCatalog.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/LockRevokerRightsCatalog.java @@ -44,15 +44,15 @@ import cwms.cda.data.dto.project.LockRevokerRights; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -96,11 +96,11 @@ public LockRevokerRightsCatalog(MetricRegistry metrics) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(type = Formats.JSON, from = LockRevokerRights.class, isArray = true)} + @OpenApiContent(type = Formats.JSON, from = LockRevokerRights[].class)} )}, tags = {TAGS}, path = PATH, - method = HttpMethod.GET + methods = HttpMethod.GET ) @Override public void handle(@NotNull Context ctx) throws Exception { @@ -120,7 +120,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve lock revoker rights", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectChildLocationHandler.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectChildLocationHandler.java index e8510d05a..1aec36f16 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectChildLocationHandler.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectChildLocationHandler.java @@ -44,14 +44,14 @@ import cwms.cda.data.dto.project.ProjectChildLocations; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -92,11 +92,11 @@ public ProjectChildLocationHandler(MetricRegistry metrics) { }, responses = { @OpenApiResponse(status = STATUS_200, content = { - @OpenApiContent(type = Formats.JSON, from = ProjectChildLocations.class, isArray = true)}) + @OpenApiContent(type = Formats.JSON, from = ProjectChildLocations[].class)}) }, tags = {TAGS}, path = PATH, - method = HttpMethod.GET + methods = HttpMethod.GET ) @Override public void handle(@NotNull Context ctx) throws Exception { @@ -116,7 +116,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Project Child Locations", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalog.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalog.java index 9ca0ece13..c90901abb 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalog.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalog.java @@ -40,7 +40,7 @@ import cwms.cda.data.dto.project.ProjectLock; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; import java.io.IOException; @@ -75,8 +75,7 @@ public void handle(@NotNull Context ctx) throws Exception { try (Timer.Context ignored = markAndTime(GET_ALL)) { ProjectLockDao lockDao = getDao(ctx); String projMask = ctx.queryParamAsClass(PROJECT_MASK, String.class).getOrDefault("*"); - String appMask = ctx.queryParamAsClass(APPLICATION_MASK, String.class).getOrDefault( - "*"); + String appMask = ctx.queryParamAsClass(APPLICATION_MASK, String.class).getOrDefault("*"); String officeMask = getOffice(ctx); List locks = lockDao.retrieveLocks(officeMask, projMask, appMask); @@ -90,7 +89,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve project locks", ex); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalogV1.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalogV1.java index 2a8be7c71..1d9b23d32 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalogV1.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalogV1.java @@ -37,12 +37,12 @@ import cwms.cda.data.dto.project.ProjectLockV1; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jetbrains.annotations.NotNull; public final class ProjectLockCatalogV1 extends ProjectLockCatalog { @@ -92,7 +92,8 @@ protected String getOffice(Context ctx) { }, tags = {TAGS}, path = PATH, - method = HttpMethod.GET + methods = HttpMethod.GET, + versions = "1" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalogV2.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalogV2.java index 5ab3eb776..3ba9d7088 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalogV2.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockCatalogV2.java @@ -36,12 +36,12 @@ import cwms.cda.data.dto.project.ProjectLockV2; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jetbrains.annotations.NotNull; public final class ProjectLockCatalogV2 extends ProjectLockCatalog { @@ -91,7 +91,8 @@ protected String getOffice(Context ctx) { }, tags = {TAGS}, path = PATH, - method = HttpMethod.GET + methods = HttpMethod.GET, + versions = "2" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOne.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOne.java index 50209b0ea..b05059a0c 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOne.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOne.java @@ -42,7 +42,7 @@ import cwms.cda.data.dto.project.ProjectLock; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; import java.io.IOException; @@ -91,7 +91,7 @@ public void handle(@NotNull Context ctx) throws Exception { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } else { ctx.status(HttpServletResponse.SC_NOT_FOUND); } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOneV1.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOneV1.java index 53c77736e..03fe3bc2a 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOneV1.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOneV1.java @@ -38,12 +38,12 @@ import cwms.cda.data.dto.project.ProjectLockV1; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jetbrains.annotations.NotNull; public final class ProjectLockGetOneV1 extends ProjectLockGetOne { @@ -89,7 +89,9 @@ protected String getOffice(Context ctx) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, tags = {TAGS}, - method = HttpMethod.GET + methods = HttpMethod.GET, + path = "/projects/lock/{" + NAME + "}", + versions = "1" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOneV2.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOneV2.java index ced63dfea..e8a9c3506 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOneV2.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockGetOneV2.java @@ -37,12 +37,12 @@ import cwms.cda.data.dto.project.ProjectLockV2; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jetbrains.annotations.NotNull; public final class ProjectLockGetOneV2 extends ProjectLockGetOne { @@ -88,7 +88,9 @@ protected String getOffice(Context ctx) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, tags = {TAGS}, - method = HttpMethod.GET + methods = HttpMethod.GET, + path = "/project/lock/{" + OFFICE + "}/{" + NAME + "}", + versions = "2" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockReleaseV1.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockReleaseV1.java index 4f6ba18b1..024ff81cf 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockReleaseV1.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockReleaseV1.java @@ -34,9 +34,9 @@ import cwms.cda.data.dao.project.ProjectLockDaoV1; import cwms.cda.data.dto.project.ProjectLockV1; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import org.jetbrains.annotations.NotNull; public final class ProjectLockReleaseV1 extends ProjectLockRelease { @@ -64,9 +64,10 @@ protected String getOffice(Context ctx) { @OpenApiParam(name = LOCK_ID, required = true, description = "The id of the lock to release."), }, - method = HttpMethod.PUT, + methods = HttpMethod.PUT, tags = {TAGS}, - path = PATH + path = PATH, + versions = "1" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockReleaseV2.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockReleaseV2.java index 6b6f9795b..ca25caedb 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockReleaseV2.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockReleaseV2.java @@ -33,9 +33,9 @@ import cwms.cda.data.dao.project.ProjectLockDaoV2; import cwms.cda.data.dto.project.ProjectLockV2; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import org.jetbrains.annotations.NotNull; public final class ProjectLockReleaseV2 extends ProjectLockRelease { @@ -65,9 +65,10 @@ protected String getOffice(Context ctx) { @OpenApiParam(name = LOCK_ID, required = true, description = "The id of the lock to release."), }, - method = HttpMethod.PUT, + methods = HttpMethod.PUT, tags = {TAGS}, - path = PATH + path = PATH, + versions = "2" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequest.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequest.java index bf4acfe80..da66825b9 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequest.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequest.java @@ -39,7 +39,7 @@ import cwms.cda.data.dto.project.ProjectLockId; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; import javax.servlet.http.HttpServletResponse; diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequestV1.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequestV1.java index 84f9ba0aa..bbeda272a 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequestV1.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequestV1.java @@ -39,12 +39,12 @@ import cwms.cda.formatters.Formats; import cwms.cda.security.DataApiPrincipal; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import org.jetbrains.annotations.NotNull; public final class ProjectLockRequestV1 extends ProjectLockRequest { @@ -61,9 +61,9 @@ protected ProjectLockDao getDao(Context ctx) { @Override protected ProjectLockV1 parseAndValidateLock(@NotNull Context ctx) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, ProjectLockV1.class); - ProjectLockV1 lock = Formats.parseContent(contentType, ctx.bodyAsInputStream(), ProjectLockV1.class); + ProjectLockV1 lock = Formats.parseContent(contentType, ctx.bodyInputStream(), ProjectLockV1.class); if (lock.getSessionUser() == null) { Object principal = ctx.attribute(AuthDao.DATA_API_PRINCIPAL); if (principal == null || !(principal instanceof DataApiPrincipal)) { @@ -98,9 +98,10 @@ protected ProjectLockV1 parseAndValidateLock(@NotNull Context ctx) { @OpenApiResponse(status = STATUS_200, content = { @OpenApiContent(type = Formats.JSON, from = ProjectLockId.class)} )}, - method = HttpMethod.POST, + methods = HttpMethod.POST, path = PATH, - tags = {TAGS} + tags = {TAGS}, + versions = "1" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequestV2.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequestV2.java index be1e02bea..bc56ce454 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequestV2.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRequestV2.java @@ -40,12 +40,12 @@ import cwms.cda.formatters.Formats; import cwms.cda.security.DataApiPrincipal; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import org.jetbrains.annotations.NotNull; public final class ProjectLockRequestV2 extends ProjectLockRequest { @@ -63,9 +63,9 @@ protected ProjectLockDao getDao(Context ctx) { @Override protected ProjectLockV2 parseAndValidateLock(@NotNull Context ctx) { String officeFromPath = ctx.pathParam(OFFICE); - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, ProjectLockV2.class); - ProjectLockV2 lock = Formats.parseContent(contentType, ctx.bodyAsInputStream(), ProjectLockV2.class); + ProjectLockV2 lock = Formats.parseContent(contentType, ctx.bodyInputStream(), ProjectLockV2.class); String officeFromBody = lock.getId() == null ? null : lock.getId().getOfficeId(); if (!officeFromPath.equalsIgnoreCase(officeFromBody)) { @@ -112,9 +112,10 @@ protected ProjectLockV2 parseAndValidateLock(@NotNull Context ctx) { @OpenApiResponse(status = STATUS_200, content = { @OpenApiContent(type = Formats.JSON, from = ProjectLockId.class)} )}, - method = HttpMethod.POST, + methods = HttpMethod.POST, path = PATH, - tags = {TAGS} + tags = {TAGS}, + versions = "2" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeDenyV1.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeDenyV1.java index b25f75c8b..ec4701f6e 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeDenyV1.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeDenyV1.java @@ -32,9 +32,9 @@ import cwms.cda.data.dao.project.ProjectLockDaoV1; import cwms.cda.data.dto.project.ProjectLockV1; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import org.jetbrains.annotations.NotNull; public final class ProjectLockRevokeDenyV1 extends ProjectLockRevokeDeny { @@ -60,9 +60,10 @@ protected String getOffice(Context ctx) { @OpenApiParam(name = LOCK_ID, required = true, description = "The id of the lock."), }, - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAGS}, - path = PATH + path = PATH, + versions = "1" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeDenyV2.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeDenyV2.java index b506b2848..50f22258d 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeDenyV2.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeDenyV2.java @@ -33,9 +33,9 @@ import cwms.cda.data.dao.project.ProjectLockDaoV2; import cwms.cda.data.dto.project.ProjectLockV2; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import org.jetbrains.annotations.NotNull; public final class ProjectLockRevokeDenyV2 extends ProjectLockRevokeDeny { @@ -65,9 +65,10 @@ protected String getOffice(Context ctx) { @OpenApiParam(name = LOCK_ID, required = true, description = "The id of the lock."), }, - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAGS}, - path = PATH + path = PATH, + versions = "2" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeV1.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeV1.java index 1e6827718..e597406e8 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeV1.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeV1.java @@ -36,9 +36,13 @@ import cwms.cda.data.dao.project.ProjectLockDaoV1; import cwms.cda.data.dto.project.ProjectLockV1; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jetbrains.annotations.NotNull; public final class ProjectLockRevokeV1 extends ProjectLockRevoke { @@ -71,9 +75,10 @@ protected String getOffice(Context ctx) { @OpenApiParam(name = REVOKE_TIMEOUT, type = Integer.class, description = "time in seconds to wait for existing lock to be revoked. Default: 10") }, - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, path = PATH, - tags = {TAGS} + tags = {TAGS}, + versions = "1" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeV2.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeV2.java index d9285cc69..1899f883e 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeV2.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectLockRevokeV2.java @@ -35,9 +35,9 @@ import cwms.cda.data.dao.project.ProjectLockDaoV2; import cwms.cda.data.dto.project.ProjectLockV2; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import org.jetbrains.annotations.NotNull; public final class ProjectLockRevokeV2 extends ProjectLockRevoke { @@ -70,9 +70,10 @@ protected String getOffice(Context ctx) { @OpenApiParam(name = REVOKE_TIMEOUT, type = Integer.class, description = "time in seconds to wait for existing lock to be revoked. Default: 10") }, - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, path = PATH, - tags = {TAGS} + tags = {TAGS}, + versions = "2" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectPublishStatusUpdate.java b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectPublishStatusUpdate.java index 1f94272a7..efdc81d77 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectPublishStatusUpdate.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/ProjectPublishStatusUpdate.java @@ -33,10 +33,13 @@ import cwms.cda.formatters.Formats; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.time.Instant; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -89,10 +92,10 @@ public ProjectPublishStatusUpdate(MetricRegistry metrics) { @OpenApiParam(name = NAME, description = "The location " + "identifier of the project that has been updated"), }, - method = HttpMethod.POST, - responses = { - @OpenApiResponse(status = STATUS_200)}, - tags = {TAG} + methods = HttpMethod.POST, + responses = {@OpenApiResponse(status = STATUS_200)}, + tags = {TAG}, + path = "/projects/publish/{" + NAME + "}" ) @Override public void handle(@NotNull Context ctx) throws Exception { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/RemoveAllLockRevokerRights.java b/cwms-data-api/src/main/java/cwms/cda/api/project/RemoveAllLockRevokerRights.java index a60c366a7..7dbdf5ef5 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/RemoveAllLockRevokerRights.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/RemoveAllLockRevokerRights.java @@ -36,9 +36,9 @@ import cwms.cda.data.dao.project.ProjectLockDaoV1; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -67,7 +67,7 @@ public RemoveAllLockRevokerRights(MetricRegistry metrics) { @OpenApiParam(name = USER_ID, required = true, description = "Specifies the user."), }, - method = HttpMethod.DELETE, + methods = HttpMethod.DELETE, path = PATH, tags = {TAGS} ) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/project/UpdateLockRevokerRights.java b/cwms-data-api/src/main/java/cwms/cda/api/project/UpdateLockRevokerRights.java index bf6a27725..930782606 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/project/UpdateLockRevokerRights.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/project/UpdateLockRevokerRights.java @@ -34,14 +34,13 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import cwms.cda.api.Controllers; -import cwms.cda.api.errors.RequiredQueryParameterException; import cwms.cda.data.dao.JooqDao; import cwms.cda.data.dao.project.ProjectLockDaoV1; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -73,7 +72,7 @@ public UpdateLockRevokerRights(MetricRegistry metrics) { @OpenApiParam(name = Controllers.ALLOW, required = true, type = Boolean.class, description = "True to add the user to the allow list, False to add to the deny list") }, - method = HttpMethod.POST, + methods = HttpMethod.POST, tags = {TAGS}, path = PATH ) From 94bb2049b43d11f40c062d7e4b07c4989a90d40b Mon Sep 17 00:00:00 2001 From: "Michael A. Neilson" Date: Wed, 30 Sep 2026 22:11:46 +0000 Subject: [PATCH 08/69] Last controllers. --- .../cwms/cda/api/TimeSeriesController.java | 4 +- .../cwms/cda/api/auth/ApiKeyController.java | 43 +++++++++------- .../AddUserListMemberController.java | 23 +++++---- .../userlists/CreateUserListController.java | 21 ++++---- .../userlists/DeleteUserListController.java | 19 +++---- .../userlists/UpdateUserListController.java | 19 +++---- .../UserListCandidatesController.java | 17 ++++--- .../auth/userlists/UserListController.java | 19 +++---- .../userlists/UserListMemberController.java | 19 +++---- .../userlists/UserListMembersController.java | 19 +++---- .../auth/userlists/UserListsController.java | 17 ++++--- .../api/auth/users/UserProfileController.java | 27 +++++----- .../cda/api/auth/users/UsersController.java | 33 ++++++------ .../auth/users/roles/AddRoleController.java | 21 ++++---- .../users/roles/DeleteRolesController.java | 21 ++++---- .../auth/users/roles/GetRolesController.java | 15 +++--- .../api/forecast/ForecastFileController.java | 15 +++--- .../forecast/ForecastInstanceController.java | 51 ++++++++++--------- .../api/forecast/ForecastSpecController.java | 14 ++--- .../forecast/ForecastSpecControllerV1.java | 43 ++++++++++------ .../forecast/ForecastSpecControllerV2.java | 42 +++++++++------ .../ForecastTimeseriesController.java | 13 +++-- 22 files changed, 282 insertions(+), 233 deletions(-) diff --git a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesController.java b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesController.java index c7ea4b923..9b2703841 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesController.java @@ -7,7 +7,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.google.common.flogger.FluentLogger; -import cwms.cda.ApiServlet; +import cwms.cda.CwmsDataApi; import cwms.cda.api.enums.UnitSystem; import cwms.cda.api.errors.CdaError; import cwms.cda.api.errors.ExceptionTraceSupport; @@ -204,7 +204,7 @@ protected DSLContext getDslContext(Context ctx) { if (ctx.method() == HandlerType.GET && ctx.attribute(AuthDao.DATA_API_PRINCIPAL) != null) { office = ctx.queryParamAsClass(OFFICE, String.class) - .getOrDefault(ctx.attribute(ApiServlet.OFFICE_ID)); + .getOrDefault(ctx.attribute(CwmsDataApi.OFFICE_ID)); } return JooqDao.getDslContext(ctx, office); } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/ApiKeyController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/ApiKeyController.java index 0f4fdebfa..9084f1ae6 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/ApiKeyController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/ApiKeyController.java @@ -45,13 +45,13 @@ import cwms.cda.security.DataApiPrincipal; import io.javalin.apibuilder.CrudHandler; import io.javalin.http.Context; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.util.List; import javax.servlet.http.HttpServletResponse; @@ -94,7 +94,8 @@ public ApiKeyController(MetricRegistry metrics) { }, description = "Create a new API Key for user. The randomly generated key is returned " + "to the caller. A provided key will be ignored." + KEY_MANAGEMENT_HELP, - tags = {"Authorization"} + tags = {"Authorization"}, + path = "/auth/keys" ) @Override public void create(Context ctx) { @@ -107,13 +108,13 @@ public void create(Context ctx) { .anyMatch(ref -> "expires".equals(ref.getFieldName()))) { message = "expires must be a valid date/time string, for example 2030-01-01T00:00:00Z."; } - ctx.json(new CdaError(message, true)).status(HttpCode.BAD_REQUEST); + ctx.json(new CdaError(message, true)).status(HttpStatus.BAD_REQUEST); return; } if (sourceData == null || sourceData.getUserId() == null || sourceData.getUserId().isBlank() || sourceData.getKeyName() == null || sourceData.getKeyName().isBlank()) { ctx.json(new CdaError("user-id and key-name are required and must not be blank.", true)) - .status(HttpCode.BAD_REQUEST); + .status(HttpStatus.BAD_REQUEST); return; } DataApiPrincipal p = ctx.attribute(AuthDao.DATA_API_PRINCIPAL); @@ -121,7 +122,7 @@ public void create(Context ctx) { DSLContext dsl = getDslContext(ctx); AuthDao auth = AuthDao.getInstance(dsl); ApiKey key = auth.createApiKey(p, sourceData); - ctx.json(key).status(HttpCode.CREATED); + ctx.json(key).status(HttpStatus.CREATED); } catch (CwmsAuthException ex) { if (ex.getMessage().equals(AuthDao.ONLY_OWN_KEY_MESSAGE)) { ctx.json(new CdaError(ex.getMessage(), true)).status(ex.getAuthFailCode()); @@ -138,7 +139,8 @@ public void create(Context ctx) { }, responses = @OpenApiResponse(status = STATUS_204), description = "Delete API key for a user." + KEY_MANAGEMENT_HELP, - tags = {"Authorization"} + tags = {"Authorization"}, + path = "/auth/keys/{key-name}" ) @Override public void delete(@NotNull Context ctx, @NotNull String keyName) { @@ -147,7 +149,7 @@ public void delete(@NotNull Context ctx, @NotNull String keyName) { AuthDao auth = AuthDao.getInstance(dsl); auth.deleteKeyForUser(p, keyName); - ctx.status(HttpCode.NO_CONTENT); + ctx.status(HttpStatus.NO_CONTENT); } @OpenApi( @@ -161,7 +163,8 @@ public void delete(@NotNull Context ctx, @NotNull String keyName) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "View all keys for the current user." + KEY_MANAGEMENT_HELP, - tags = {"Authorization"} + tags = {"Authorization"}, + path = "/auth/keys" ) public void getAll(Context ctx) { DataApiPrincipal p = ctx.attribute(AuthDao.DATA_API_PRINCIPAL); @@ -170,7 +173,7 @@ public void getAll(Context ctx) { AuthDao auth = AuthDao.getInstance(dsl); List keys = auth.apiKeysForUser(p); - ctx.json(keys).status(HttpCode.OK); + ctx.json(keys).status(HttpStatus.OK); } @@ -189,7 +192,8 @@ public void getAll(Context ctx) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "View specific key metadata. The secret cannot be retrieved." + KEY_MANAGEMENT_HELP, - tags = {"Authorization"} + tags = {"Authorization"}, + path = "/auth/keys/{key-name}" ) @Override public void getOne(Context ctx, @NotNull String keyName) { @@ -198,19 +202,20 @@ public void getOne(Context ctx, @NotNull String keyName) { AuthDao auth = AuthDao.getInstance(dsl); ApiKey key = auth.apiKeyForUser(p, keyName); if (key != null) { - ctx.json(key).status(HttpCode.OK); + ctx.json(key).status(HttpStatus.OK); } else { CdaError msg = new CdaError( "Requested Key was not found. NOTE: api key names are case-sensitive.", true ); - ctx.json(msg).status(HttpCode.NOT_FOUND); + ctx.json(msg).status(HttpStatus.NOT_FOUND); } } @OpenApi( - ignore = true // users should delete and recreate keys. There is nothing to update. + ignore = true, // users should delete and recreate keys. There is nothing to update. + path = "" ) @Override public void update(@NotNull Context ctx, @NotNull String arg1) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/AddUserListMemberController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/AddUserListMemberController.java index 2a6e53097..72e0ca4ac 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/AddUserListMemberController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/AddUserListMemberController.java @@ -17,14 +17,14 @@ import cwms.cda.formatters.Formats; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jooq.DSLContext; public final class AddUserListMemberController implements Handler { @@ -52,8 +52,9 @@ public AddUserListMemberController(MetricRegistry metrics) { }, security = @OpenApiSecurity(name = "gets overridden allows lock icon."), description = "Add an existing CWMS user to an office-scoped user list.", - method = HttpMethod.POST, - tags = UserListController.TAG + methods = HttpMethod.POST, + tags = UserListController.TAG, + path = "/user-lists/add/{" + USER_LIST_ID + "}" // TODO: fix ) @Override public void handle(Context ctx) { @@ -68,7 +69,7 @@ public void handle(Context ctx) { UserListSupport.requireOfficeAdmin(ctx, dao, office); UserListMemberInput input = ctx.bodyAsClass(UserListMemberInput.class); String userId = UserListSupport.validateUserId(input.getUserId()); - ctx.status(HttpCode.CREATED).json(dao.addMember( + ctx.status(HttpStatus.CREATED).json(dao.addMember( office, UserListSupport.validateUserListId(ctx.pathParam(USER_LIST_ID)), userId, UserListSupport.principal(ctx).getName())); } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/CreateUserListController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/CreateUserListController.java index ec6a53052..9fa696c77 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/CreateUserListController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/CreateUserListController.java @@ -15,13 +15,13 @@ import cwms.cda.formatters.Formats; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jooq.DSLContext; public final class CreateUserListController implements Handler { @@ -45,8 +45,9 @@ public CreateUserListController(MetricRegistry metrics) { }, security = @OpenApiSecurity(name = "gets overridden allows lock icon."), description = "Create an office-scoped user list owned by the authenticated user.", - method = HttpMethod.POST, - tags = UserListController.TAG + methods = HttpMethod.POST, + tags = UserListController.TAG, + path = "/user-lists" ) @Override public void handle(Context ctx) { @@ -64,7 +65,7 @@ public void handle(Context ctx) { UserListSupport.requireOfficeAdmin(ctx, dao, office); UserList created = dao.createUserList(office, userListId, description, UserListSupport.principal(ctx).getName()); - ctx.status(HttpCode.CREATED).json(created); + ctx.status(HttpStatus.CREATED).json(created); } } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/DeleteUserListController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/DeleteUserListController.java index cedcae19a..423809c3c 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/DeleteUserListController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/DeleteUserListController.java @@ -14,12 +14,12 @@ import cwms.cda.data.dao.UserListDao; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jooq.DSLContext; public final class DeleteUserListController implements Handler { @@ -43,8 +43,9 @@ public DeleteUserListController(MetricRegistry metrics) { }, security = @OpenApiSecurity(name = "gets overridden allows lock icon."), description = "Delete a user list and its membership rows.", - method = HttpMethod.DELETE, - tags = UserListController.TAG + methods = HttpMethod.DELETE, + tags = UserListController.TAG, + path = "/user-list" // TODO: fix ) @Override public void handle(Context ctx) { @@ -59,7 +60,7 @@ public void handle(Context ctx) { UserListSupport.requireOfficeAdmin(ctx, dao, office); dao.deleteUserList(office, UserListSupport.validateUserListId(ctx.pathParam(USER_LIST_ID))); - ctx.status(HttpCode.NO_CONTENT); + ctx.status(HttpStatus.NO_CONTENT); } } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UpdateUserListController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UpdateUserListController.java index fdb773d84..55c72ccf2 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UpdateUserListController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UpdateUserListController.java @@ -17,13 +17,13 @@ import cwms.cda.formatters.Formats; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jooq.DSLContext; public final class UpdateUserListController implements Handler { @@ -50,8 +50,9 @@ public UpdateUserListController(MetricRegistry metrics) { }, security = @OpenApiSecurity(name = "gets overridden allows lock icon."), description = "Update user-list metadata. Creator ownership is immutable.", - method = HttpMethod.PATCH, - tags = UserListController.TAG + methods = HttpMethod.PATCH, + tags = UserListController.TAG, + path = "/user-lists/" // TODO: fix ) @Override public void handle(Context ctx) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListCandidatesController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListCandidatesController.java index 6147b11b2..4cadeb04c 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListCandidatesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListCandidatesController.java @@ -14,12 +14,12 @@ import cwms.cda.formatters.Formats; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jooq.DSLContext; public final class UserListCandidatesController implements Handler { @@ -46,8 +46,9 @@ public UserListCandidatesController(MetricRegistry metrics) { }, security = @OpenApiSecurity(name = "gets overridden allows lock icon."), description = "Search existing CWMS users for user-list membership.", - method = HttpMethod.GET, - tags = UserListController.TAG + methods = HttpMethod.GET, + tags = UserListController.TAG, + path = "/user-lists/candidates" // TODO: fix ) @Override public void handle(Context ctx) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListController.java index ab162d864..88317f405 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListController.java @@ -18,15 +18,15 @@ import cwms.cda.data.dto.auth.userlists.UserList; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jooq.DSLContext; public final class UserListController implements Handler { @@ -65,8 +65,9 @@ private Timer.Context markAndTime(String subject) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "Retrieve user list metadata.", - method = HttpMethod.GET, - tags = {TAG} + methods = HttpMethod.GET, + tags = {TAG}, + path = "/user-lists" // TODO: fix ) @Override public void handle(Context ctx) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListMemberController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListMemberController.java index b77191e03..607e73e0b 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListMemberController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListMemberController.java @@ -15,12 +15,12 @@ import cwms.cda.data.dao.UserListDao; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jooq.DSLContext; public final class UserListMemberController implements Handler { @@ -48,8 +48,9 @@ public UserListMemberController(MetricRegistry metrics) { }, security = @OpenApiSecurity(name = "gets overridden allows lock icon."), description = "Remove a member from an office-scoped user list.", - method = HttpMethod.DELETE, - tags = UserListController.TAG + methods = HttpMethod.DELETE, + tags = UserListController.TAG, + path = "/users/list/members" // TODO: FIX ) @Override public void handle(Context ctx) { @@ -65,7 +66,7 @@ metrics, getClass().getName(), DELETE)) { dao.removeMember(office, UserListSupport.validateUserListId(ctx.pathParam(USER_LIST_ID)), UserListSupport.validateUserId(ctx.pathParam(USER_ID))); - ctx.status(HttpCode.NO_CONTENT); + ctx.status(HttpStatus.NO_CONTENT); } } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListMembersController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListMembersController.java index b2989ea5f..a26fd7eb0 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListMembersController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListMembersController.java @@ -17,15 +17,15 @@ import cwms.cda.data.dto.auth.userlists.UserListMembers; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jooq.DSLContext; public final class UserListMembersController implements Handler { @@ -64,8 +64,9 @@ private Timer.Context markAndTime(String subject) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "Retrieve the members of a user list.", - method = HttpMethod.GET, - tags = {TAG} + methods = HttpMethod.GET, + tags = {TAG}, + path = "/user/list/members" // TODO: fix ) @Override public void handle(Context ctx) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListsController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListsController.java index aeb37bac8..5e204a5a3 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListsController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/userlists/UserListsController.java @@ -15,12 +15,12 @@ import cwms.cda.formatters.Formats; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import org.jooq.DSLContext; public final class UserListsController implements Handler { @@ -41,8 +41,9 @@ public UserListsController(MetricRegistry metrics) { }, security = @OpenApiSecurity(name = "gets overridden allows lock icon."), description = "List office-scoped reusable user lists.", - method = HttpMethod.GET, - tags = UserListController.TAG + methods = HttpMethod.GET, + tags = UserListController.TAG, + path = "/user/lists" // TODO :fix ) @Override public void handle(Context ctx) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/UserProfileController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/UserProfileController.java index 12773d8fe..ebe0b2a72 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/UserProfileController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/UserProfileController.java @@ -4,7 +4,7 @@ import static cwms.cda.data.dao.JooqDao.getDslContext; import com.codahale.metrics.MetricRegistry; -import cwms.cda.ApiServlet; +import cwms.cda.CwmsDataApi; import cwms.cda.data.dao.AuthDao; import cwms.cda.data.dao.UserDao; import cwms.cda.data.dto.auth.users.User; @@ -12,14 +12,16 @@ import cwms.cda.formatters.Formats; import cwms.cda.security.DataApiPrincipal; import cwms.cda.security.Role; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import javax.servlet.http.HttpServletResponse; import org.jooq.DSLContext; @@ -42,8 +44,9 @@ public UserProfileController(MetricRegistry metrics) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "View users' own information", - method = HttpMethod.GET, - tags = {"User Management"} + methods = HttpMethod.GET, + tags = {"User Management"}, + path = "/user/profile" ) @Override public void handle(Context ctx) throws Exception { @@ -52,8 +55,8 @@ public void handle(Context ctx) throws Exception { UserDao dao = new UserDao(dsl); String cac_user = p.getRoles() .stream() - .filter(r -> r.equals(new Role(ApiServlet.CAC_USER))) - .map(r -> ApiServlet.CAC_USER) + .filter(r -> r.equals(new Role(CwmsDataApi.CAC_USER))) + .map(r -> CwmsDataApi.CAC_USER) .findFirst().orElse(null); User user = dao.getByUniqueName(p.getName(), cac_user).orElse(null); String formatHeader = ctx.header(Header.ACCEPT); @@ -65,7 +68,7 @@ public void handle(Context ctx) throws Exception { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/UsersController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/UsersController.java index 30688f3e4..a466d36c8 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/UsersController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/UsersController.java @@ -29,14 +29,14 @@ import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; import io.javalin.apibuilder.CrudHandler; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import org.jooq.DSLContext; @@ -56,13 +56,13 @@ private Timer.Context markAndTime(String subject) { return Controllers.markAndTime(metrics, getClass().getName(), subject); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(Context ctx, String username) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -110,7 +110,8 @@ public void delete(Context ctx, String username) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "View all users", - tags = {TAG} + tags = {TAG}, + path = "/users" ) @Override public void getAll(Context ctx) { @@ -127,7 +128,7 @@ public void getAll(Context ctx) { if (!CwmsDTOPaginated.CURSOR_CHECK.invoke(cursor)) { ctx.json(new CdaError("cursor or page passed in but failed validation")) - .status(HttpCode.BAD_REQUEST); + .status(HttpStatus.BAD_REQUEST); return; } @@ -147,7 +148,7 @@ public void getAll(Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve Users", ex); @@ -175,7 +176,8 @@ public void getAll(Context ctx) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "View specific user", - tags = {TAG} + tags = {TAG}, + path = "/user/{user-name}" ) @Override public void getOne(Context ctx, String userName) { @@ -193,7 +195,7 @@ public void getOne(Context ctx, String userName) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (IOException ex) { CdaError error = ExceptionTraceSupport.buildError(ctx, "Failed to process request to retrieve User", ex); @@ -203,7 +205,8 @@ public void getOne(Context ctx, String userName) { } @OpenApi( - ignore = true // users cannot be updated. Rolls are handled by a separate endpoint. + ignore = true, // users cannot be updated. Rolls are handled by a separate endpoint. + path = "" ) @Override public void update(Context ctx, String arg1) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/AddRoleController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/AddRoleController.java index 345feae90..0b8c69b99 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/AddRoleController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/AddRoleController.java @@ -14,13 +14,13 @@ import cwms.cda.security.DataApiPrincipal; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; public class AddRoleController implements Handler { private final MetricRegistry metrics; @@ -44,14 +44,15 @@ public AddRoleController(MetricRegistry metrics) { }, requestBody = @OpenApiRequestBody( content = { - @OpenApiContent(from = String[].class, type = Formats.JSON, isArray = true) + @OpenApiContent(from = String[].class, type = Formats.JSON) } ), security = { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "Add roles to user", - tags = {"User Management"} + tags = {"User Management"}, + path = "/roles/add/{office-id}/{user-name}" // TODO: check ) @Override public void handle(Context ctx) throws Exception { @@ -61,7 +62,7 @@ public void handle(Context ctx) throws Exception { final String[] roles = ctx.bodyAsClass(String[].class); UserDao dao = new UserDao(getDslContext(ctx)); dao.addRoles(p, user, office, roles); - ctx.status(HttpCode.NO_CONTENT); + ctx.status(HttpStatus.NO_CONTENT); } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/DeleteRolesController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/DeleteRolesController.java index bed14eb94..46e73a79d 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/DeleteRolesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/DeleteRolesController.java @@ -12,13 +12,13 @@ import cwms.cda.security.DataApiPrincipal; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; public class DeleteRolesController implements Handler { private final MetricRegistry metrics; @@ -40,14 +40,15 @@ public DeleteRolesController(MetricRegistry metrics) { ), requestBody = @OpenApiRequestBody( content = { - @OpenApiContent(from = String[].class, type = Formats.JSON, isArray = true) + @OpenApiContent(from = String[].class, type = Formats.JSON) } ), security = { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "Remove roles from user", - tags = {"User Management"} + tags = {"User Management"}, + path = "/roles/{office-id}/{user-name}" ) @Override public void handle(Context ctx) throws Exception { @@ -57,7 +58,7 @@ public void handle(Context ctx) throws Exception { final String[] roles = ctx.bodyAsClass(String[].class); UserDao dao = new UserDao(getDslContext(ctx)); dao.deleteRoles(p, user, office, roles); - ctx.status(HttpCode.NO_CONTENT); + ctx.status(HttpStatus.NO_CONTENT); } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/GetRolesController.java b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/GetRolesController.java index 4bdd15d9a..96287aa81 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/GetRolesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/auth/users/roles/GetRolesController.java @@ -13,11 +13,11 @@ import cwms.cda.security.DataApiPrincipal; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.http.HttpCode; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; -import io.javalin.plugin.openapi.annotations.OpenApiSecurity; +import io.javalin.http.HttpStatus; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiResponse; +import io.javalin.openapi.OpenApiSecurity; public class GetRolesController implements Handler { private final MetricRegistry metrics; @@ -37,14 +37,15 @@ public GetRolesController(MetricRegistry metrics) { @OpenApiSecurity(name = "gets overridden allows lock icon.") }, description = "View all roles", - tags = {"User Management"} + tags = {"User Management"}, + path = "/roles" ) @Override public void handle(Context ctx) throws Exception { final DataApiPrincipal p = ctx.attribute(AuthDao.DATA_API_PRINCIPAL); UserDao dao = new UserDao(getDslContext(ctx)); List roles = dao.getRoles(); - ctx.json(roles).status(HttpCode.OK); + ctx.json(roles).status(HttpStatus.OK); } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastFileController.java b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastFileController.java index 938a64d4c..cc96c78dd 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastFileController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastFileController.java @@ -34,13 +34,13 @@ import cwms.cda.data.dao.forecast.ForecastInstanceDao; import cwms.cda.data.dao.StreamConsumer; import cwms.cda.helpers.DateUtils; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import io.javalin.http.Handler; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiResponse; import org.jetbrains.annotations.NotNull; import javax.servlet.http.HttpServletResponse; @@ -95,12 +95,13 @@ private Timer.Context markAndTime(String subject) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - tags = {ForecastSpecController.TAG} + tags = {ForecastSpecController.TAG}, + path = "/forecasts/files" ) public void handle(@NotNull Context ctx) { String specId = ctx.pathParam(NAME); String office = requiredParam(ctx, OFFICE); - String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).allowNullable().get(); + String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).getOrNull(); String forecastDate = requiredParam(ctx, FORECAST_DATE); String issueDate = requiredParam(ctx, ISSUE_DATE); Instant forecastInstant = DateUtils.parseUserDate(forecastDate, "UTC").toInstant(); diff --git a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastInstanceController.java b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastInstanceController.java index e95a2907b..d0570fec7 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastInstanceController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastInstanceController.java @@ -30,14 +30,14 @@ import cwms.cda.formatters.FormattingException; import cwms.cda.helpers.DateUtils; import cwms.cda.helpers.ReplaceUtils; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import java.io.IOException; import java.net.URISyntaxException; import java.time.Instant; @@ -69,8 +69,9 @@ protected DSLContext getDslContext(Context ctx) { }, required = true ), - method = HttpMethod.POST, - tags = TAG + methods = HttpMethod.POST, + tags = TAG, + path = "/forecasts/instance" ) @Override public void create(@NotNull Context ctx) { @@ -106,14 +107,15 @@ public void create(@NotNull Context ctx) { @OpenApiResponse(status = STATUS_404, description = "The provided combination of " + "parameters did not find a forecast instance."), }, - method = HttpMethod.DELETE, - tags = TAG + methods = HttpMethod.DELETE, + tags = TAG, + path = "/forecast/instance/{" + NAME + "}" ) @Override public void delete(@NotNull Context ctx, @NotNull String name) { String office = requiredParam(ctx, OFFICE); - String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).allowNullable().get(); + String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).getOrNull(); String forecastDate = requiredParam(ctx, FORECAST_DATE); String issueDate = requiredParam(ctx, ISSUE_DATE); Instant forecastInstant = DateUtils.parseUserDate(forecastDate, "UTC").toInstant(); @@ -147,14 +149,15 @@ public void delete(@NotNull Context ctx, @NotNull String name) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.GET, - tags = TAG + methods = HttpMethod.GET, + tags = TAG, + path = "/forecasts/instance" ) @Override public void getAll(@NotNull Context ctx) { try (final Timer.Context ignored = markAndTime(GET_ALL)) { String office = ctx.queryParam(OFFICE); - String designatorMask = ctx.queryParamAsClass(DESIGNATOR, String.class).allowNullable().get(); + String designatorMask = ctx.queryParamAsClass(DESIGNATOR, String.class).getOrNull(); String name = ctx.queryParam(NAME); ForecastInstanceDao dao = new ForecastInstanceDao(getDslContext(ctx)); @@ -184,7 +187,7 @@ public void getAll(@NotNull Context ctx) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (URISyntaxException e) { throw new FormattingException("Could not build file download URL", e); } catch (IOException ex) { @@ -225,13 +228,14 @@ public void getAll(@NotNull Context ctx) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.GET, - tags = TAG + methods = HttpMethod.GET, + tags = TAG, + path = "/forecast/instance/{" + NAME + "}" ) @Override public void getOne(@NotNull Context ctx, @NotNull String name) { String office = requiredParam(ctx, OFFICE); - String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).allowNullable().get(); + String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).getOrNull(); String forecastDate = requiredParam(ctx, FORECAST_DATE); String issueDate = requiredParam(ctx, ISSUE_DATE); Instant forecastInstant = DateUtils.parseUserDate(forecastDate, "UTC").toInstant(); @@ -263,7 +267,7 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } catch (URISyntaxException e) { throw new FormattingException("Could not build file download URL", e); } catch (IOException ex) { @@ -290,8 +294,9 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " + "inputs provided the ForecastInstance was not found.") }, - method = HttpMethod.PATCH, - tags = TAG + methods = HttpMethod.PATCH, + tags = TAG, + path = "/forecasts/instance/{" + NAME + "}" ) @Override public void update(@NotNull Context ctx, @NotNull String name) { @@ -305,7 +310,7 @@ public void update(@NotNull Context ctx, @NotNull String name) { } private ForecastInstance deserializeForecastInstance(Context ctx) { - String formatHeader = ctx.req.getContentType(); + String formatHeader = ctx.contentType(); ContentType contentType = Formats.parseHeader(formatHeader, ForecastInstance.class); return Formats.parseContent(contentType, ctx.body(), ForecastInstance.class); } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecController.java b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecController.java index 92943b34c..5c8178081 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecController.java @@ -25,7 +25,7 @@ import cwms.cda.data.dto.CwmsDTOBase; import cwms.cda.formatters.ContentType; import cwms.cda.formatters.Formats; -import io.javalin.core.util.Header; +import io.javalin.http.Header; import io.javalin.http.Context; import java.io.IOException; import java.util.List; @@ -66,7 +66,7 @@ public void create(@NotNull Context ctx) { } protected void delete(Context ctx, String name, String office) { - String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).allowNullable().get(); + String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).getOrNull(); JooqDao.DeleteMethod deleteMethod = ctx.queryParamAsClass(METHOD, JooqDao.DeleteMethod.class) .getOrDefault(JooqDao.DeleteMethod.DELETE_KEY); @@ -97,9 +97,9 @@ protected void delete(Context ctx, String name, String office) { protected void getAll(Context ctx, String office) { try (final Timer.Context ignored = markAndTime(GET_ALL)) { String names = ctx.queryParamAsClass(ID_MASK, String.class).getOrDefault("*"); - String designator = ctx.queryParamAsClass(DESIGNATOR_MASK, String.class).allowNullable().get(); + String designator = ctx.queryParamAsClass(DESIGNATOR_MASK, String.class).getOrNull(); String sourceEntity = ctx.queryParamAsClass(SOURCE_ENTITY, String.class).getOrDefault("*"); - String entityLike = ctx.queryParamAsClass(SOURCE_ENTITY_LIKE, String.class).allowNullable().get(); + String entityLike = ctx.queryParamAsClass(SOURCE_ENTITY_LIKE, String.class).getOrNull(); DSLContext dsl = getDslContext(ctx); ForecastSpecDao dao = newDao(dsl); @@ -114,7 +114,7 @@ protected void getAll(Context ctx, String office) { protected void getOne(Context ctx, String name, String office) { try (final Timer.Context ignored = markAndTime(GET_ONE)) { - String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).allowNullable().get(); + String designator = ctx.queryParamAsClass(DESIGNATOR, String.class).getOrNull(); DSLContext dsl = getDslContext(ctx); ForecastSpecDao dao = newDao(dsl); @@ -157,7 +157,7 @@ private void writeBytes(Context ctx, ContentType contentType, String result) thr byte[] bytes = result.getBytes(); ctx.header(Header.CONTENT_LENGTH, String.valueOf(bytes.length)); - ctx.res.getOutputStream().write(bytes); + ctx.outputStream().write(bytes); } private void handleWriteFailure(Context ctx, IOException ex, String message) { @@ -167,7 +167,7 @@ private void handleWriteFailure(Context ctx, IOException ex, String message) { } protected T deserializeForecastSpec(Context ctx) { - ContentType contentType = Formats.parseHeader(ctx.req.getContentType(), getDtoClass()); + ContentType contentType = Formats.parseHeader(ctx.contentType(), getDtoClass()); return Formats.parseContent(contentType, ctx.body(), getDtoClass()); } } diff --git a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecControllerV1.java b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecControllerV1.java index cc6682ead..7d9e68fe0 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecControllerV1.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecControllerV1.java @@ -21,12 +21,12 @@ import cwms.cda.data.dto.forecast.ForecastSpec; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -55,8 +55,10 @@ protected Class getDtoClass() { }, required = true ), - method = HttpMethod.POST, - tags = TAG + methods = HttpMethod.POST, + tags = TAG, + path = "/forecasts/spec", + versions = "1" ) @Override public void create(@NotNull Context ctx) { @@ -82,8 +84,11 @@ public void create(@NotNull Context ctx) { @OpenApiResponse(status = STATUS_404, description = "The provided combination of " + "parameters did not find a forecast spec."), }, - method = HttpMethod.DELETE, - tags = TAG + methods = HttpMethod.DELETE, + path = "/forecasts/spec/{" + NAME + "}", + tags = TAG, + versions = "1" + ) @Override public void delete(@NotNull Context ctx, @NotNull String name) { @@ -118,8 +123,10 @@ public void delete(@NotNull Context ctx, @NotNull String name) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.GET, - tags = TAG + methods = HttpMethod.GET, + tags = TAG, + path = "/forecasts/spec", + versions = "1" ) @Override public void getAll(@NotNull Context ctx) { @@ -151,8 +158,10 @@ public void getAll(@NotNull Context ctx) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.GET, - tags = TAG + methods = HttpMethod.GET, + tags = TAG, + path = "/forecasts/spec/{" + NAME + "}", + versions = "1" ) @Override public void getOne(@NotNull Context ctx, @NotNull String name) { @@ -174,8 +183,10 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " + "inputs provided the forecast spec was not found.") }, - method = HttpMethod.PATCH, - tags = TAG + methods = HttpMethod.PATCH, + tags = TAG, + path = "/forecasts/spec/{" + NAME + "}", + versions = "1" ) @Override public void update(@NotNull Context ctx, @NotNull String name) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecControllerV2.java b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecControllerV2.java index 04e44f7cb..eb052f085 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecControllerV2.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastSpecControllerV2.java @@ -20,12 +20,12 @@ import cwms.cda.data.dto.forecast.ForecastSpecV2; import cwms.cda.formatters.Formats; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.HttpMethod; -import io.javalin.plugin.openapi.annotations.OpenApi; -import io.javalin.plugin.openapi.annotations.OpenApiContent; -import io.javalin.plugin.openapi.annotations.OpenApiParam; -import io.javalin.plugin.openapi.annotations.OpenApiRequestBody; -import io.javalin.plugin.openapi.annotations.OpenApiResponse; +import io.javalin.openapi.OpenApi; +import io.javalin.openapi.HttpMethod; +import io.javalin.openapi.OpenApiContent; +import io.javalin.openapi.OpenApiParam; +import io.javalin.openapi.OpenApiRequestBody; +import io.javalin.openapi.OpenApiResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -58,8 +58,10 @@ protected Class getDtoClass() { }, required = true ), - method = HttpMethod.POST, - tags = TAG + methods = HttpMethod.POST, + tags = TAG, + path = "/forecasts/spec", + versions = "2" ) @Override public void create(@NotNull Context ctx) { @@ -87,8 +89,10 @@ public void create(@NotNull Context ctx) { @OpenApiResponse(status = STATUS_404, description = "The provided combination of " + "parameters did not find a forecast spec."), }, - method = HttpMethod.DELETE, - tags = TAG + methods = HttpMethod.DELETE, + tags = TAG, + path = "/forecast/spec/{" + OFFICE + "}/{" + NAME + "}", + versions = "2" ) @Override public void delete(@NotNull Context ctx, @NotNull String name) { @@ -125,8 +129,10 @@ public void delete(@NotNull Context ctx, @NotNull String name) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.GET, - tags = TAG + methods = HttpMethod.GET, + tags = TAG, + path = "/forecast/spec", + versions = "2" ) @Override public void getAll(@NotNull Context ctx) { @@ -158,8 +164,10 @@ public void getAll(@NotNull Context ctx) { @OpenApiResponse(status = STATUS_501, description = "Requested format is not " + "implemented") }, - method = HttpMethod.GET, - tags = TAG + methods = HttpMethod.GET, + tags = TAG, + path = "/forecast/spec/{" + OFFICE + "}/{" + NAME + "}", + versions = "2" ) @Override public void getOne(@NotNull Context ctx, @NotNull String name) { @@ -183,8 +191,10 @@ public void getOne(@NotNull Context ctx, @NotNull String name) { @OpenApiResponse(status = STATUS_404, description = "Based on the combination of " + "inputs provided the forecast spec was not found.") }, - method = HttpMethod.PATCH, - tags = TAG + methods = HttpMethod.PATCH, + tags = TAG, + path = "/forecasts/spec/{" + OFFICE + "}/{" + NAME + "}", + versions = "2" ) @Override public void update(@NotNull Context ctx, @NotNull String name) { diff --git a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastTimeseriesController.java b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastTimeseriesController.java index e19ceeac7..293db2e2f 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastTimeseriesController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/forecast/ForecastTimeseriesController.java @@ -8,8 +8,7 @@ import cwms.cda.data.dao.JooqDao; import io.javalin.apibuilder.CrudHandler; import io.javalin.http.Context; -import io.javalin.plugin.openapi.annotations.OpenApi; - +import io.javalin.openapi.OpenApi; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.jooq.DSLContext; @@ -35,7 +34,7 @@ private Timer.Context markAndTime(String subject) { return Controllers.markAndTime(metrics, getClass().getName(), subject); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void create(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); @@ -45,25 +44,25 @@ protected DSLContext getDslContext(Context ctx) { return JooqDao.getDslContext(ctx); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void delete(@NotNull Context ctx, @NotNull String forecastSpecId) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getAll(@NotNull Context ctx) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void getOne(@NotNull Context ctx, @NotNull String id) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); } - @OpenApi(ignore = true) + @OpenApi(ignore = true, path = "") @Override public void update(@NotNull Context ctx, @NotNull String id) { ctx.status(HttpServletResponse.SC_NOT_IMPLEMENTED).json(CdaError.notImplemented()); From 168317f01eedaec3e0a24ddf033f42435cf5cd2f Mon Sep 17 00:00:00 2001 From: "Michael A. Neilson" Date: Wed, 30 Sep 2026 22:35:51 +0000 Subject: [PATCH 09/69] Start on baseline javalin changes. --- .../main/groovy/cda.deps-conventions.gradle | 3 - .../cda/ApiServletRouteConfiguration.java | 59 +-- .../cda/{ApiServlet.java => CwmsDataApi.java} | 371 ++++++++---------- .../main/java/cwms/cda/data/dao/AuthDao.java | 18 +- .../java/cwms/cda/data/dao/CdaVersionDao.java | 4 +- .../main/java/cwms/cda/data/dao/JooqDao.java | 18 +- .../java/cwms/cda/openapi/ExampleUtils.java | 5 +- .../cda/openapi/OpenApiSchemeProcessor.java | 7 +- .../cda/security/ApiKeyIdentityProvider.java | 4 +- .../cwms/cda/security/CdaAccessManager.java | 20 +- .../cda/security/CwmsAaaIdentityProvider.java | 8 +- .../cwms/cda/security/DataApiPrincipal.java | 2 +- .../OpenIdConnectIdentityProvider.java | 4 +- .../src/main/java/cwms/cda/security/Role.java | 2 +- .../test/java/cwms/cda/ApiServletTest.java | 10 +- .../api/BinaryTimeSeriesControllerTestIT.java | 14 +- .../api/ForecastInstanceControllerTestIT.java | 4 +- .../api/ForecastSpecControllerV1TestIT.java | 6 +- .../api/ForecastSpecControllerV2TestIT.java | 6 +- .../cwms/cda/api/LevelsControllerTestIT.java | 8 +- .../api/TextTimeSeriesControllerTestIT.java | 14 +- .../TimeSeriesCategoryControllerTestIT.java | 4 +- .../cda/api/TimeSeriesDirectReadParityIT.java | 4 +- .../TimeSeriesGroupControllerV1TestIT.java | 20 +- ...sIdentifierDescriptorControllerTestIT.java | 14 +- .../api/TimeSeriesProfileControllerIT.java | 6 +- ...TimeSeriesProfileInstanceControllerIT.java | 12 +- .../cda/api/TimeseriesControllerTestIT.java | 12 +- .../cda/api/auth/ApiKeyControllerTestIT.java | 4 +- .../src/test/java/fixtures/TestAccounts.java | 12 +- .../java/fixtures/users/UserSpecSource.java | 2 +- gradle/libs.versions.toml | 2 +- 32 files changed, 314 insertions(+), 365 deletions(-) rename cwms-data-api/src/main/java/cwms/cda/{ApiServlet.java => CwmsDataApi.java} (53%) diff --git a/buildSrc/src/main/groovy/cda.deps-conventions.gradle b/buildSrc/src/main/groovy/cda.deps-conventions.gradle index 597546c99..252bd2ba0 100644 --- a/buildSrc/src/main/groovy/cda.deps-conventions.gradle +++ b/buildSrc/src/main/groovy/cda.deps-conventions.gradle @@ -13,9 +13,6 @@ repositories { excludeModule("javax.media", "jai_core") } - maven { - url = uri('https://repo.maven.apache.org/maven2') - } gradlePluginPortal() } diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServletRouteConfiguration.java b/cwms-data-api/src/main/java/cwms/cda/ApiServletRouteConfiguration.java index 738497542..22dc5c773 100644 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServletRouteConfiguration.java +++ b/cwms-data-api/src/main/java/cwms/cda/ApiServletRouteConfiguration.java @@ -1,7 +1,7 @@ package cwms.cda; -import static cwms.cda.ApiServlet.CAC_USER; -import static cwms.cda.ApiServlet.CWMS_USERS_ROLE; +import static cwms.cda.CwmsDataApi.CAC_USER; +import static cwms.cda.CwmsDataApi.CWMS_USERS_ROLE; import static cwms.cda.api.Controllers.CONTRACT_NAME; import static cwms.cda.api.Controllers.LOCATION_ID; import static cwms.cda.api.Controllers.NAME; @@ -162,11 +162,11 @@ import cwms.cda.security.MissingRolesException; import cwms.cda.security.Role; import io.javalin.Javalin; -import io.javalin.apibuilder.CrudFunction; import io.javalin.apibuilder.CrudHandler; -import io.javalin.apibuilder.CrudHandlerKt; -import io.javalin.core.security.RouteRole; -import io.javalin.core.util.Header; +import io.javalin.config.RoutesConfig; +import io.javalin.security.RouteRole; +import io.javalin.http.Header; +import io.javalin.http.HttpStatus; import io.javalin.http.Context; import io.javalin.http.Handler; import org.jetbrains.annotations.NotNull; @@ -185,8 +185,11 @@ private ApiServletRouteConfiguration() { throw new AssertionError("Utility class - do not instantiate"); } - public static void configureRoutes(MetricRegistry metrics, RouteRole[] requiredRoles, CdaAccessManager cdaAccessManager) { + public static void configureRoutes(RoutesConfig routes, MetricRegistry metrics, RouteRole[] requiredRoles, CdaAccessManager cdaAccessManager) { + routes.apiBuilder(() ->{ + + get("/", ctx -> ctx.result("Welcome to the CWMS REST API") .contentType(Formats.PLAIN)); // Even view on this one requires authorization @@ -410,6 +413,7 @@ public static void configureRoutes(MetricRegistry metrics, RouteRole[] requiredR get("/version/", new CdaVersionHandler(metrics), requiredRoles); get(format("/rss/{%s}/{%s}", Controllers.OFFICE, Controllers.NAME), new RssHandler(metrics)); + }); } private static void addUserManagementHandlers(MetricRegistry metrics, CdaAccessManager cdaAccessManager) { @@ -666,10 +670,10 @@ private static void cdaCrudCache(@NotNull String path, @NotNull CrudHandler crud private static void addCacheControl(@NotNull String path, long duration, TimeUnit timeUnit) { if (timeUnit != null && duration > 0) { staticInstance().after(path, ctx -> { - String method = ctx.req.getMethod(); // "GET" - if (ctx.status() == HttpServletResponse.SC_OK + String method = ctx.method().name(); // "GET" + if (ctx.status() == HttpStatus.OK && "GET".equals(method) - && (!ctx.res.containsHeader(Header.CACHE_CONTROL))) { + && (!ctx.res().containsHeader(Header.CACHE_CONTROL))) { // only set the cache control header if it is not already set. ctx.header(Header.CACHE_CONTROL, "max-age=" + timeUnit.toSeconds(duration)); } @@ -706,24 +710,25 @@ private static void cdaCrud(@NotNull String path, @NotNull CrudHandler crudHandl String fullPath = prefixPath(path); String resourceId = getResourceId(fullPath); + // TODO. methods used below no longer exist //noinspection KotlinInternalInJava - Map crudFunctions = CrudHandlerKt.getCrudFunctions(crudHandler, resourceId); - - Javalin instance = staticInstance(); - // getOne and getAll are assumed not to need authorization - String pathWithoutResource = fullPath.replace(resourceId, ""); - if (getRequiresAuth) { - instance.get(fullPath, crudFunctions.get(CrudFunction.GET_ONE), roles); - instance.get(pathWithoutResource, crudFunctions.get(CrudFunction.GET_ALL), roles); - } else { - instance.get(fullPath, crudFunctions.get(CrudFunction.GET_ONE)); - instance.get(pathWithoutResource, crudFunctions.get(CrudFunction.GET_ALL)); - } - - // create, update and delete need authorization. - instance.post(pathWithoutResource, crudFunctions.get(CrudFunction.CREATE), roles); - instance.patch(fullPath, crudFunctions.get(CrudFunction.UPDATE), roles); - instance.delete(fullPath, crudFunctions.get(CrudFunction.DELETE), roles); + // Map crudFunctions = CrudHandlerKt.getCrudFunctions(crudHandler, resourceId); + + // Javalin instance = staticInstance(); + // // getOne and getAll are assumed not to need authorization + // String pathWithoutResource = fullPath.replace(resourceId, ""); + // if (getRequiresAuth) { + // instance.get(fullPath, crudFunctions.get(CrudFunction.GET_ONE), roles); + // instance.get(pathWithoutResource, crudFunctions.get(CrudFunction.GET_ALL), roles); + // } else { + // instance.get(fullPath, crudFunctions.get(CrudFunction.GET_ONE)); + // instance.get(pathWithoutResource, crudFunctions.get(CrudFunction.GET_ALL)); + // } + + // // create, update and delete need authorization. + // instance.post(pathWithoutResource, crudFunctions.get(CrudFunction.CREATE), roles); + // instance.patch(fullPath, crudFunctions.get(CrudFunction.UPDATE), roles); + // instance.delete(fullPath, crudFunctions.get(CrudFunction.DELETE), roles); } /** diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/CwmsDataApi.java similarity index 53% rename from cwms-data-api/src/main/java/cwms/cda/ApiServlet.java rename to cwms-data-api/src/main/java/cwms/cda/CwmsDataApi.java index 44bb43e68..ccd1e63c6 100644 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java +++ b/cwms-data-api/src/main/java/cwms/cda/CwmsDataApi.java @@ -24,69 +24,37 @@ package cwms.cda; -import static cwms.cda.openapi.ExampleUtils.addEndpointExamples; - -import com.codahale.metrics.Meter; import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.servlets.MetricsServlet; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.google.common.flogger.FluentLogger; -import cwms.cda.api.Controllers; import cwms.cda.api.auth.userlists.UserListController; -import cwms.cda.api.enums.UnitSystem; import cwms.cda.api.errors.ApplicationException; import cwms.cda.api.errors.CdaError; import cwms.cda.api.errors.ExceptionTraceSupport; -import cwms.cda.data.dao.JooqDao; -import cwms.cda.data.dao.rss.QueueManager; -import cwms.cda.data.dto.csv.CwmsCsvDTO; -import cwms.cda.formatters.Formats; -import cwms.cda.formatters.csv.CsvExampleGenerator; import cwms.cda.openapi.OpenApiSchemeProcessor; import cwms.cda.security.Authenticator; import cwms.cda.security.CdaAccessManager; import cwms.cda.security.Role; -import io.github.classgraph.ClassGraph; -import io.github.classgraph.ScanResult; import io.javalin.Javalin; -import io.javalin.core.JavalinConfig; -import io.javalin.core.security.RouteRole; -import io.javalin.core.util.Header; -import io.javalin.core.validation.JavalinValidation; +import io.javalin.config.JavalinConfig; +import io.javalin.config.Key; +import io.javalin.config.RoutesConfig; +import io.javalin.security.RouteRole; import io.javalin.http.BadRequestResponse; -import io.javalin.http.JavalinServlet; -import io.javalin.plugin.openapi.OpenApiOptions; -import io.javalin.plugin.openapi.OpenApiPlugin; -import io.javalin.validation.Validator; +import io.javalin.openapi.plugin.OpenApiPlugin; import io.opentelemetry.api.trace.Span; -import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.media.MediaType; -import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.security.SecurityRequirement; -import io.swagger.v3.oas.models.servers.Server; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.time.DateTimeException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.jar.Manifest; import javax.annotation.Resource; -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; import org.apache.http.entity.ContentType; @@ -141,7 +109,7 @@ "/rss/*", "/v2/*" }) -public class ApiServlet extends HttpServlet { +public final class CwmsDataApi { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); @@ -165,69 +133,53 @@ public class ApiServlet extends HttpServlet { public static final String DEFAULT_OFFICE_KEY = "cwms.dataapi.default.office"; public static final String DEFAULT_PROVIDER = "MultipleAccessManager"; - private MetricRegistry metrics; - private Meter totalRequests; - - private static final long serialVersionUID = 1L; - - JavalinServlet javalin = null; - private final Authenticator authenticator = new Authenticator(); - private final OpenApiSchemeProcessor schemeProcessor = new OpenApiSchemeProcessor(authenticator); - private String appContext; + - @Resource(name = "jdbc/CWMS3") + @Resource(name = "jdbc/CWMS3") // TODO: sort out DataSource cwms; - private CdaAccessManager cdaAccessManager; public static String getApiVersion() { return VERSION != null ? VERSION : "Not Yet Known"; } - - @Override - public void destroy() { - javalin.destroy(); - } - - @Override - public void init(ServletConfig config) throws ServletException { - if (VERSION == null) { - ApiServlet.VERSION = obtainFullVersion(config); - } - logger.atInfo().log("Initializing CWMS Data API Version: " + VERSION); - metrics = (MetricRegistry)config.getServletContext() - .getAttribute(MetricsServlet.METRICS_REGISTRY); - totalRequests = metrics.meter("cwms.dataapi.total_requests"); - - super.init(config); - } + @SuppressWarnings({"java:S125","java:S2095"}) // closed in destroy handler - @Override - public void init() { + public static void main(String[] args) { + logger.atInfo().log("Initializing Javalin."); - - JavalinValidation.register(UnitSystem.class, UnitSystem::systemFor); - JavalinValidation.register(JooqDao.DeleteMethod.class, Controllers::getDeleteMethod); - + final MetricRegistry metrics = new MetricRegistry(); + // TODO: move to config + // JavalinValidation.register(UnitSystem.class, UnitSystem::systemFor); + // JavalinValidation.register(JooqDao.DeleteMethod.class, Controllers::getDeleteMethod); + var totalRequests = metrics.meter("cwms.dataapi.total_requests"); ObjectMapper om = new ObjectMapper(); om.setPropertyNamingStrategy(PropertyNamingStrategies.KEBAB_CASE); om.registerModule(new JavaTimeModule()); PolicyFactory sanitizer = new HtmlPolicyBuilder().disallowElements("