diff --git a/pom.xml b/pom.xml index 661068f93f..8a4daf2411 100644 --- a/pom.xml +++ b/pom.xml @@ -81,7 +81,6 @@ 2.3.2 1.1 3.0.1 - 3.1.0 3.29.2-GA 3.5.2.Final 4.4.3 @@ -94,8 +93,8 @@ 0.2.0 3.7.1 1.4.3 - 1.11.5 - 1.11.5 + 1.12.0 + 1.12.0 1.12 2.17.0 4.1.72.Final @@ -119,9 +118,11 @@ 1.4.0 2.0.6 2.2 - 3.1.5 - 6.1.5 - 2.2.7 + 2.3.0 + 6.1.1 + 3.2.0 + 6.2.0 + 2.2.19 0.8.1 1.11 @@ -154,6 +155,13 @@ + + org.springframework + spring-framework-bom + ${spring.version} + import + pom + commons-codec commons-codec @@ -339,11 +347,6 @@ persistence-api ${jakarta-persistence-api.version} - - jakarta.ws.rs - jakarta.ws.rs-api - ${jakarta.ws.rs.version} - org.apache.activemq activemq-client @@ -510,6 +513,11 @@ spring-security-core ${spring-security.version} + + org.springframework.security + spring-security-web + ${spring-security.version} + org.yaml snakeyaml @@ -743,6 +751,11 @@ quartz ${quartz.version} + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + redis.clients jedis @@ -975,6 +988,7 @@ 17 UTF-8 + true @@ -1264,6 +1278,7 @@ 17 UTF-8 + true diff --git a/streampipes-extensions/streampipes-extensions-all-iiot/Dockerfile b/streampipes-extensions/streampipes-extensions-all-iiot/Dockerfile index a53114ad38..ae8040391e 100644 --- a/streampipes-extensions/streampipes-extensions-all-iiot/Dockerfile +++ b/streampipes-extensions/streampipes-extensions-all-iiot/Dockerfile @@ -23,4 +23,4 @@ COPY --from=builder dependencies/ ./ COPY --from=builder snapshot-dependencies/ ./ COPY --from=builder spring-boot-loader/ ./ COPY --from=builder application/ ./ -ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"] +ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"] diff --git a/streampipes-extensions/streampipes-extensions-all-jvm/Dockerfile b/streampipes-extensions/streampipes-extensions-all-jvm/Dockerfile index 558320271d..31c59268e2 100644 --- a/streampipes-extensions/streampipes-extensions-all-jvm/Dockerfile +++ b/streampipes-extensions/streampipes-extensions-all-jvm/Dockerfile @@ -26,4 +26,4 @@ COPY --from=builder dependencies/ ./ COPY --from=builder snapshot-dependencies/ ./ COPY --from=builder spring-boot-loader/ ./ COPY --from=builder application/ ./ -ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"] +ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"] diff --git a/streampipes-extensions/streampipes-extensions-iiot-minimal/Dockerfile b/streampipes-extensions/streampipes-extensions-iiot-minimal/Dockerfile index 5c449815c5..621162a874 100644 --- a/streampipes-extensions/streampipes-extensions-iiot-minimal/Dockerfile +++ b/streampipes-extensions/streampipes-extensions-iiot-minimal/Dockerfile @@ -23,4 +23,4 @@ COPY --from=builder dependencies/ ./ COPY --from=builder snapshot-dependencies/ ./ COPY --from=builder spring-boot-loader/ ./ COPY --from=builder application/ ./ -ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"] +ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"] diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java index 7e2747595c..26f5d1c003 100644 --- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java +++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/user/Role.java @@ -57,8 +57,9 @@ public enum Role { ), ROLE_CONNECT_ADMIN( Constants.ROLE_CONNECT_ADMIN_VALUE, - Privilege.PRIVILEGE_WRITE_ADAPTER - + Privilege.PRIVILEGE_WRITE_ADAPTER, + Privilege.PRIVILEGE_READ_ADAPTER, + Privilege.PRIVILEGE_DELETE_ADAPTER ), ROLE_DASHBOARD_USER( diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/message/Notification.java b/streampipes-model/src/main/java/org/apache/streampipes/model/message/Notification.java index 272a6fd731..283072d828 100644 --- a/streampipes-model/src/main/java/org/apache/streampipes/model/message/Notification.java +++ b/streampipes-model/src/main/java/org/apache/streampipes/model/message/Notification.java @@ -34,7 +34,8 @@ public Notification(String title, String description) { this.description = description; } - public Notification(String title, String description, + public Notification(String title, + String description, String additionalInformation) { super(); this.title = title; @@ -42,7 +43,8 @@ public Notification(String title, String description, this.additionalInformation = additionalInformation; } - public Notification(NotificationType notificationType, String additionalInformation) { + public Notification(NotificationType notificationType, + String additionalInformation) { this(notificationType.title(), notificationType.description(), additionalInformation); } diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeImageResource.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeImageResource.java index 0b90d72e66..6e71ec1a36 100644 --- a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeImageResource.java +++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeImageResource.java @@ -21,19 +21,21 @@ import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource; import org.apache.streampipes.storage.management.StorageDispatcher; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.Response; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -@Path("v4/datalake/images") + +import java.io.InputStream; + +@RestController +@RequestMapping("/api/v4/datalake/images") public class DataLakeImageResource extends AbstractAuthGuardedRestResource { - @GET - @Path("{imageId}") - @Produces("image/jpeg") - public Response getImage(@PathParam("imageId") String imageId) { + @GetMapping(path = "{imageId}", produces = "image/jpeg") + public ResponseEntity getImage(@PathVariable("imageId") String imageId) { return ok(StorageDispatcher.INSTANCE.getNoSqlStore().getImageStorage().getImageBytes(imageId)); } } diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV4.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV4.java index 7ed976cbc8..f315571cff 100644 --- a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV4.java +++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeMeasureResourceV4.java @@ -23,25 +23,26 @@ import org.apache.streampipes.dataexplorer.influx.DataLakeMeasurementCount; import org.apache.streampipes.model.datalake.DataLakeMeasure; import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; import org.apache.streampipes.storage.management.StorageDispatcher; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.PUT; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import java.util.List; +import java.util.Map; import java.util.Objects; -@Path("/v4/datalake/measure") +@RestController +@RequestMapping("/api/v4/datalake/measure") public class DataLakeMeasureResourceV4 extends AbstractAuthGuardedRestResource { private final IDataExplorerSchemaManagement dataLakeMeasureManagement; @@ -53,29 +54,24 @@ public DataLakeMeasureResourceV4() { this.dataLakeMeasureManagement = new DataExplorerSchemaManagement(dataLakeStorage); } - @POST - @JacksonSerialized - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response addDataLake(DataLakeMeasure dataLakeMeasure) { + @PostMapping( + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE + ) + public ResponseEntity addDataLake(@RequestBody DataLakeMeasure dataLakeMeasure) { DataLakeMeasure result = this.dataLakeMeasureManagement.createOrUpdateMeasurement(dataLakeMeasure); return ok(result); } - @GET - @JacksonSerialized - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response getDataLakeInfos(@QueryParam("filter") List measurementNames) { + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getDataLakeInfos( + @RequestParam(value = "filter", required = false) List measurementNames) { var allMeasurements = this.dataLakeMeasureManagement.getAllMeasurements(); return ok(new DataLakeMeasurementCount(allMeasurements, measurementNames).countMeasurementSizes()); } - @GET - @JacksonSerialized - @Produces(MediaType.APPLICATION_JSON) - @Path("{id}") - public Response getDataLakeMeasure(@PathParam("id") String elementId) { + @GetMapping(path = "{id}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getDataLakeMeasure(@PathVariable("id") String elementId) { var measure = this.dataLakeMeasureManagement.getById(elementId); if (Objects.nonNull(measure)) { return ok(measure); @@ -84,15 +80,9 @@ public Response getDataLakeMeasure(@PathParam("id") String elementId) { } } - @PUT - @JacksonSerialized - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @Path("{id}") - public Response updateDataLakeMeasure( - @PathParam("id") String elementId, - DataLakeMeasure measure - ) { + @PutMapping(path = "{id}", consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity updateDataLakeMeasure(@PathVariable("id") String elementId, + @RequestBody DataLakeMeasure measure) { if (elementId.equals(measure.getElementId())) { try { this.dataLakeMeasureManagement.updateMeasurement(measure); @@ -104,10 +94,8 @@ public Response updateDataLakeMeasure( return badRequest(); } - @DELETE - @JacksonSerialized - @Path("{id}") - public Response deleteDataLakeMeasure(@PathParam("id") String elementId) { + @DeleteMapping(path = "{id}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity deleteDataLakeMeasure(@PathVariable("id") String elementId) { try { this.dataLakeMeasureManagement.deleteMeasurement(elementId); return ok(); diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV3.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV3.java index f24c5e9879..99c2191c63 100644 --- a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV3.java +++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV3.java @@ -21,27 +21,24 @@ import org.apache.streampipes.dataexplorer.utils.DataExplorerUtils; import org.apache.streampipes.model.datalake.DataLakeMeasure; import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.List; -@Path("/v3/datalake") +@RestController +@RequestMapping("/api/v3/datalake") @Deprecated public class DataLakeResourceV3 extends AbstractRestResource { public DataLakeResourceV3() { } - @GET - @JacksonSerialized - @Produces(MediaType.APPLICATION_JSON) - @Path("/info") - public Response getAllInfos() { + @GetMapping(path = "/info", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getAllInfos() { List result = DataExplorerUtils.getInfos(); return ok(result); } diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java index f2ba8b46c2..93e6b26f4d 100644 --- a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java +++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeResourceV4.java @@ -25,8 +25,10 @@ import org.apache.streampipes.model.datalake.DataLakeMeasure; import org.apache.streampipes.model.datalake.DataSeries; import org.apache.streampipes.model.datalake.SpQueryResult; +import org.apache.streampipes.model.message.Notifications; import org.apache.streampipes.model.monitoring.SpLogMessage; import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; +import org.apache.streampipes.rest.shared.exception.SpMessageException; import org.apache.streampipes.storage.management.StorageDispatcher; import io.swagger.v3.oas.annotations.Operation; @@ -36,21 +38,18 @@ import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.MultivaluedMap; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.StreamingOutput; -import jakarta.ws.rs.core.UriInfo; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import java.util.HashMap; import java.util.List; @@ -76,10 +75,11 @@ import static org.apache.streampipes.dataexplorer.param.SupportedRestQueryParams.QP_TIME_INTERVAL; import static org.apache.streampipes.dataexplorer.param.SupportedRestQueryParams.SUPPORTED_PARAMS; -@Path("v4/datalake") +@RestController +@RequestMapping("/api/v4/datalake") public class DataLakeResourceV4 extends AbstractRestResource { - private DataExplorerQueryManagement dataLakeManagement; + private final DataExplorerQueryManagement dataLakeManagement; private final DataExplorerSchemaManagement dataExplorerSchemaManagement; public DataLakeResourceV4() { @@ -98,26 +98,24 @@ public DataLakeResourceV4(DataExplorerQueryManagement dataLakeManagement) { this.dataExplorerSchemaManagement = new DataExplorerSchemaManagement(dataLakeStorage); } - @DELETE - @Path("/measurements/{measurementID}") + @DeleteMapping(path = "/measurements/{measurementID}") @Operation(summary = "Remove data from a single measurement series with given id", tags = {"Data Lake"}, responses = { @ApiResponse(responseCode = "200", description = "Data from measurement series successfully removed"), @ApiResponse(responseCode = "400", description = "Measurement series with given id not found")}) - public Response deleteData( + public ResponseEntity deleteData( @Parameter(in = ParameterIn.PATH, description = "the id of the measurement series", required = true) - @PathParam("measurementID") String measurementID - , @Parameter(in = ParameterIn.QUERY, description = "start date for slicing operation") @QueryParam("startDate") - Long startDate - , @Parameter(in = ParameterIn.QUERY, description = "end date for slicing operation") @QueryParam("endDate") - Long endDate) { + @PathVariable("measurementID") String measurementID + , @Parameter(in = ParameterIn.QUERY, description = "start date for slicing operation") + @RequestParam(value = "startDate", required = false) Long startDate + , @Parameter(in = ParameterIn.QUERY, description = "end date for slicing operation") + @RequestParam(value = "endDate", required = false) Long endDate) { SpQueryResult result = this.dataLakeManagement.deleteData(measurementID, startDate, endDate); return ok(); } - @DELETE - @Path("/measurements/{measurementID}/drop") + @DeleteMapping(path = "/measurements/{measurementID}/drop") @Operation(summary = "Drop a single measurement series with given id from Data Lake and " + "remove related event property", tags = { @@ -129,9 +127,9 @@ public Response deleteData( @ApiResponse( responseCode = "400", description = "Measurement series with given id or related event property not found")}) - public Response dropMeasurementSeries( + public ResponseEntity dropMeasurementSeries( @Parameter(in = ParameterIn.PATH, description = "the id of the measurement series", required = true) - @PathParam("measurementID") String measurementID) { + @PathVariable("measurementID") String measurementID) { boolean isSuccessDataLake = this.dataLakeManagement.deleteData(measurementID); @@ -140,41 +138,38 @@ public Response dropMeasurementSeries( if (isSuccessEventProperty) { return ok(); } else { - return Response.status(Response.Status.NOT_FOUND) - .entity("Event property related to measurement series with given id not found.").build(); + return ResponseEntity + .status(HttpStatus.NOT_FOUND) + .body("Event property related to measurement series with given id not found."); } } else { - return Response.status(Response.Status.NOT_FOUND).entity("Measurement series with given id not found.").build(); + return ResponseEntity + .status(HttpStatus.NOT_FOUND) + .body("Measurement series with given id not found."); } } - @GET - @Path("/measurements") - @Produces(MediaType.APPLICATION_JSON) + @GetMapping(path = "/measurements/", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Get a list of all measurement series", tags = {"Data Lake"}, responses = { @ApiResponse( responseCode = "200", description = "array of stored measurement series", content = @Content(array = @ArraySchema(schema = @Schema(implementation = DataLakeMeasure.class))))}) - public Response getAll() { + public ResponseEntity> getAll() { List allMeasurements = this.dataExplorerSchemaManagement.getAllMeasurements(); return ok(allMeasurements); } - @GET - @Path("/measurements/{measurementId}/tags") - @Produces(MediaType.APPLICATION_JSON) - public Response getTagValues(@PathParam("measurementId") String measurementId, - @QueryParam("fields") String fields) { + @GetMapping(path = "/measurements/{measurementId}/tags", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getTagValues(@PathVariable("measurementId") String measurementId, + @RequestParam("fields") String fields) { Map tagValues = dataLakeManagement.getTagValues(measurementId, fields); return ok(tagValues); } - @GET - @Path("/measurements/{measurementID}") - @Produces(MediaType.APPLICATION_JSON) + @GetMapping(path = "/measurements/{measurementID}", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Get data from a single measurement series by a given id", tags = {"Data Lake"}, responses = { @ApiResponse( @@ -183,56 +178,55 @@ public Response getTagValues(@PathParam("measurementId") String measurementId, @ApiResponse( responseCode = "200", description = "requested data", content = @Content(schema = @Schema(implementation = DataSeries.class)))}) - public Response getData( + public ResponseEntity getData( @Parameter(in = ParameterIn.PATH, description = "the id of the measurement series", required = true) - @PathParam("measurementID") String measurementID + @PathVariable("measurementID") String measurementID , @Parameter(in = ParameterIn.QUERY, description = "the columns to be selected (comma-separated)") - @QueryParam(QP_COLUMNS) String columns - , @Parameter(in = ParameterIn.QUERY, description = "start date for slicing operation") @QueryParam(QP_START_DATE) - Long startDate - , @Parameter(in = ParameterIn.QUERY, description = "end date for slicing operation") @QueryParam(QP_END_DATE) - Long endDate - , @Parameter(in = ParameterIn.QUERY, description = "page number for paging operation") @QueryParam(QP_PAGE) - Integer page + @RequestParam(value = QP_COLUMNS, required = false) String columns + , @Parameter(in = ParameterIn.QUERY, description = "start date for slicing operation") + @RequestParam(value = QP_START_DATE, required = false) Long startDate + , @Parameter(in = ParameterIn.QUERY, description = "end date for slicing operation") + @RequestParam(value = QP_END_DATE, required = false) Long endDate + , @Parameter(in = ParameterIn.QUERY, description = "page number for paging operation") + @RequestParam(value = QP_PAGE, required = false) Integer page , @Parameter(in = ParameterIn.QUERY, description = "maximum number of retrieved query results") - @QueryParam(QP_LIMIT) Integer limit - , @Parameter(in = ParameterIn.QUERY, description = "offset") @QueryParam(QP_OFFSET) Integer offset + @RequestParam(value = QP_LIMIT, required = false) Integer limit + , @Parameter(in = ParameterIn.QUERY, description = "offset") + @RequestParam(value = QP_OFFSET, required = false) Integer offset , @Parameter(in = ParameterIn.QUERY, description = "grouping tags (comma-separated) for grouping operation") - @QueryParam(QP_GROUP_BY) String groupBy + @RequestParam(value = QP_GROUP_BY, required = false) String groupBy , @Parameter( in = ParameterIn.QUERY, description = "ordering of retrieved query results (ASC or DESC - default is ASC)") - @QueryParam(QP_ORDER) String order + @RequestParam(value = QP_ORDER, required = false) String order , @Parameter(in = ParameterIn.QUERY, description = "name of aggregation function used for grouping operation") - @QueryParam(QP_AGGREGATION_FUNCTION) String aggregationFunction + @RequestParam(value = QP_AGGREGATION_FUNCTION, required = false) String aggregationFunction , @Parameter( in = ParameterIn.QUERY, description = "time interval for aggregation (e.g. 1m - one minute) for grouping operation") - @QueryParam(QP_TIME_INTERVAL) String timeInterval - , @Parameter(in = ParameterIn.QUERY, description = "only return the number of results") @QueryParam(QP_COUNT_ONLY) - String countOnly + @RequestParam(value = QP_TIME_INTERVAL, required = false) String timeInterval + , @Parameter(in = ParameterIn.QUERY, description = "only return the number of results") + @RequestParam(value = QP_COUNT_ONLY, required = false) String countOnly , @Parameter(in = ParameterIn.QUERY, description = "auto-aggregate the number of results to avoid browser overload") - @QueryParam(QP_AUTO_AGGREGATE) boolean autoAggregate + @RequestParam(value = QP_AUTO_AGGREGATE, required = false) boolean autoAggregate , @Parameter( in = ParameterIn.QUERY, description = "filter conditions (a comma-separated list of filter conditions" + "such as [field,operator,condition])") - @QueryParam(QP_FILTER) String filter + @RequestParam(value = QP_FILTER, required = false) String filter , @Parameter(in = ParameterIn.QUERY, description = "missingValueBehaviour (ignore or empty)") - @QueryParam(QP_MISSING_VALUE_BEHAVIOUR) String missingValueBehaviour + @RequestParam(value = QP_MISSING_VALUE_BEHAVIOUR, required = false) String missingValueBehaviour , @Parameter( in = ParameterIn.QUERY, description = "the maximum amount of resulting events," + "when too high the query status is set to TOO_MUCH_DATA") - @QueryParam(QP_MAXIMUM_AMOUNT_OF_EVENTS) Integer maximumAmountOfResults - , @Context UriInfo uriInfo) { - - MultivaluedMap queryParams = uriInfo.getQueryParameters(); + @RequestParam(value = QP_MAXIMUM_AMOUNT_OF_EVENTS, required = false) Integer maximumAmountOfResults, + @RequestParam Map queryParams) { if (!(checkProvidedQueryParams(queryParams))) { return badRequest(); @@ -248,11 +242,11 @@ public Response getData( } } - @POST - @Path("/query") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response getData(List> queryParams) { + @PostMapping( + path = "/query", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getData(List> queryParams) { var results = queryParams .stream() .map(qp -> new ProvidedRestQueryParams(qp.get("measureName"), qp)) @@ -262,9 +256,7 @@ public Response getData(List> queryParams) { return ok(results); } - @GET - @Path("/measurements/{measurementID}/download") - @Produces(MediaType.APPLICATION_OCTET_STREAM) + @GetMapping(path = "/measurements/{measurementID}/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) @Operation(summary = "Download data from a single measurement series by a given id", tags = {"Data Lake"}, responses = { @ApiResponse( @@ -273,55 +265,55 @@ public Response getData(List> queryParams) { @ApiResponse( responseCode = "200", description = "requested data", content = @Content(schema = @Schema(implementation = DataSeries.class)))}) - public Response downloadData( + public ResponseEntity downloadData( @Parameter(in = ParameterIn.PATH, description = "the id of the measurement series", required = true) - @PathParam("measurementID") String measurementID + @PathVariable("measurementID") String measurementID , @Parameter(in = ParameterIn.QUERY, description = "the columns to be selected (comma-separated)") - @QueryParam(QP_COLUMNS) String columns - , @Parameter(in = ParameterIn.QUERY, description = "start date for slicing operation") @QueryParam(QP_START_DATE) - Long startDate - , @Parameter(in = ParameterIn.QUERY, description = "end date for slicing operation") @QueryParam(QP_END_DATE) - Long endDate - , @Parameter(in = ParameterIn.QUERY, description = "page number for paging operation") @QueryParam(QP_PAGE) - Integer page + @RequestParam(value = QP_COLUMNS, required = false) String columns + , @Parameter(in = ParameterIn.QUERY, description = "start date for slicing operation") + @RequestParam(value = QP_START_DATE, required = false) Long startDate + , @Parameter(in = ParameterIn.QUERY, description = "end date for slicing operation") + @RequestParam(value = QP_END_DATE, required = false) Long endDate + , @Parameter(in = ParameterIn.QUERY, description = "page number for paging operation") + @RequestParam(value = QP_PAGE, required = false) Integer page , @Parameter(in = ParameterIn.QUERY, description = "maximum number of retrieved query results") - @QueryParam(QP_LIMIT) Integer limit - , @Parameter(in = ParameterIn.QUERY, description = "offset") @QueryParam(QP_OFFSET) Integer offset + @RequestParam(value = QP_LIMIT, required = false) Integer limit + , @Parameter(in = ParameterIn.QUERY, description = "offset") + @RequestParam(value = QP_OFFSET, required = false) Integer offset , @Parameter(in = ParameterIn.QUERY, description = "grouping tags (comma-separated) for grouping operation") - @QueryParam(QP_GROUP_BY) String groupBy + @RequestParam(value = QP_GROUP_BY, required = false) String groupBy , @Parameter( in = ParameterIn.QUERY, description = "ordering of retrieved query results (ASC or DESC - default is ASC)") - @QueryParam(QP_ORDER) String order + @RequestParam(value = QP_ORDER, required = false) String order , @Parameter(in = ParameterIn.QUERY, description = "name of aggregation function used for grouping operation") - @QueryParam(QP_AGGREGATION_FUNCTION) String aggregationFunction + @RequestParam(value = QP_AGGREGATION_FUNCTION, required = false) String aggregationFunction , @Parameter( in = ParameterIn.QUERY, description = "time interval for aggregation (e.g. 1m - one minute) for grouping operation") - @QueryParam(QP_TIME_INTERVAL) String timeInterval + @RequestParam(value = QP_TIME_INTERVAL, required = false) String timeInterval , @Parameter( in = ParameterIn.QUERY, description = "format specification (csv, json - default is csv) for data download") - @QueryParam(QP_FORMAT) String format + @RequestParam(value = QP_FORMAT, required = false) String format , @Parameter(in = ParameterIn.QUERY, description = "csv delimiter (comma or semicolon)") - @QueryParam(QP_CSV_DELIMITER) String csvDelimiter + @RequestParam(value = QP_CSV_DELIMITER, required = false) String csvDelimiter , @Parameter(in = ParameterIn.QUERY, description = "missingValueBehaviour (ignore or empty)") - @QueryParam(QP_MISSING_VALUE_BEHAVIOUR) String missingValueBehaviour + @RequestParam(value = QP_MISSING_VALUE_BEHAVIOUR, required = false) String missingValueBehaviour , @Parameter( in = ParameterIn.QUERY, description = "filter conditions (a comma-separated list of filter conditions" + "such as [field,operator,condition])") - @QueryParam(QP_FILTER) String filter - , @Context UriInfo uriInfo) { + @RequestParam(value = QP_FILTER, required = false) String filter, + @RequestParam Map queryParams) { - MultivaluedMap queryParams = uriInfo.getQueryParameters(); if (!(checkProvidedQueryParams(queryParams))) { - return badRequest(); + throw new SpMessageException(HttpStatus.BAD_REQUEST, Notifications.error("Wrong query parameters provided")); } else { ProvidedRestQueryParams sanitizedParams = populate(measurementID, queryParams); if (format == null) { @@ -329,33 +321,36 @@ public Response downloadData( } OutputFormat outputFormat = format.equals("csv") ? OutputFormat.CSV : OutputFormat.JSON; - StreamingOutput streamingOutput = output -> dataLakeManagement.getDataAsStream( + StreamingResponseBody streamingOutput = output -> dataLakeManagement.getDataAsStream( sanitizedParams, outputFormat, isIgnoreMissingValues(missingValueBehaviour), output); - return Response.ok(streamingOutput, MediaType.APPLICATION_OCTET_STREAM). - header("Content-Disposition", "attachment; filename=\"datalake." + outputFormat + "\"") - .build(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", "datalake." + outputFormat); + + return ResponseEntity.ok() + .headers(headers) + .body(streamingOutput); } } - @DELETE - @Path("/measurements") + @DeleteMapping(path = "/measurements") @Operation(summary = "Remove all stored measurement series from Data Lake", tags = {"Data Lake"}, responses = { @ApiResponse(responseCode = "200", description = "All measurement series successfully removed")}) - public Response removeAll() { + public ResponseEntity removeAll() { boolean isSuccess = this.dataLakeManagement.deleteAllData(); - return Response.ok(isSuccess).build(); + return ResponseEntity.ok(isSuccess); } - private boolean checkProvidedQueryParams(MultivaluedMap providedParams) { + private boolean checkProvidedQueryParams(Map providedParams) { return SUPPORTED_PARAMS.containsAll(providedParams.keySet()); } - private ProvidedRestQueryParams populate(String measurementId, MultivaluedMap rawParams) { + private ProvidedRestQueryParams populate(String measurementId, Map rawParams) { Map queryParamMap = new HashMap<>(); rawParams.forEach((key, value) -> queryParamMap.put(key, String.join(",", value))); diff --git a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/PipelineElementTemplateResource.java b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/PipelineElementTemplateResource.java index 5d5c959da8..ff93e04803 100644 --- a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/PipelineElementTemplateResource.java +++ b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/PipelineElementTemplateResource.java @@ -25,7 +25,6 @@ import org.apache.streampipes.model.graph.DataSinkInvocation; import org.apache.streampipes.model.template.PipelineElementTemplate; import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -34,25 +33,24 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.PUT; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -@Path("/v2/pipeline-element-templates") +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/api/v2/pipeline-element-templates") public class PipelineElementTemplateResource extends AbstractRestResource { - @GET - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Get a list of all pipeline element templates", tags = {"Pipeline Element Templates"}, responses = { @@ -62,8 +60,9 @@ public class PipelineElementTemplateResource extends AbstractRestResource { array = @ArraySchema(schema = @Schema(implementation = PipelineElementTemplate.class))) }) }) - public Response getAll(@Parameter(description = "Filter all templates by this appId") - @QueryParam("appId") String appId) { + public ResponseEntity> getAll( + @Parameter(description = "Filter all templates by this appId") + @RequestParam("appId") String appId) { if (appId == null) { return ok(getPipelineElementTemplateStorage().getAll()); } else { @@ -71,10 +70,7 @@ public Response getAll(@Parameter(description = "Filter all templates by this ap } } - @GET - @Path("{id}") - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized + @GetMapping(path = "{id}", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Get a single pipeline element template by a given id", tags = {"Pipeline Element Templates"}, responses = { @@ -85,8 +81,8 @@ public Response getAll(@Parameter(description = "Filter all templates by this ap }), @ApiResponse(responseCode = "400", description = "Template with given id not found") }) - public Response getById(@Parameter(description = "The id of the pipeline element template", required = true) - @PathParam("id") String s) { + public ResponseEntity getById(@Parameter(description = "The id of the pipeline element template", required = true) + @PathVariable("id") String s) { try { return ok(getPipelineElementTemplateStorage().getElementById(s)); } catch (RuntimeException e) { @@ -94,26 +90,20 @@ public Response getById(@Parameter(description = "The id of the pipeline element } } - @POST - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized + @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Store a new pipeline element template", tags = {"Pipeline Element Templates"}, responses = { @ApiResponse(responseCode = "200", description = "Template successfully stored") }) - public Response create(@RequestBody(description = "The pipeline element template to be stored", + public ResponseEntity create(@RequestBody(description = "The pipeline element template to be stored", content = @Content(schema = @Schema(implementation = PipelineElementTemplate.class))) - PipelineElementTemplate entity) { + PipelineElementTemplate entity) { getPipelineElementTemplateStorage().createElement(entity); return ok(); } - @PUT - @Path("{id}") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized + @PutMapping(path = "{id}", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Update a pipeline element template", tags = {"Pipeline Element Templates"}, responses = { @@ -124,8 +114,9 @@ public Response create(@RequestBody(description = "The pipeline element template }, responseCode = "200", description = "Template successfully updated"), @ApiResponse(responseCode = "400", description = "Template with given id not found") }) - public Response update(@Parameter(description = "The id of the pipeline element template", required = true) - @PathParam("id") String id, PipelineElementTemplate entity) { + public ResponseEntity update(@Parameter(description = "The id of the pipeline element template", required = true) + @PathVariable("id") String id, + @RequestBody PipelineElementTemplate entity) { try { if (id.equals(entity.getCouchDbId())) { return ok(getPipelineElementTemplateStorage().updateElement(entity)); @@ -137,26 +128,25 @@ public Response update(@Parameter(description = "The id of the pipeline element } } - @DELETE - @Path("{id}") + @DeleteMapping(path = "{id}") @Operation(summary = "Delete a pipeline element template by a given id", tags = {"Pipeline Element Templates"}, responses = { @ApiResponse(responseCode = "200", description = "Pipeline element template successfully deleted"), @ApiResponse(responseCode = "400", description = "Template with given id not found") }) - public Response delete(@Parameter(description = "The id of the pipeline element template", required = true) - @PathParam("id") String s) { + public ResponseEntity delete( + @Parameter(description = "The id of the pipeline element template", required = true) + @PathVariable("id") String s) { PipelineElementTemplate template = getPipelineElementTemplateStorage().getElementById(s); getPipelineElementTemplateStorage().deleteElement(template); return ok(); } - @POST - @Path("{id}/sink") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized + @PostMapping( + path = "{id}/sink", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Configure a data sink with a pipeline element template.", tags = {"Pipeline Element Templates"}, responses = { @@ -166,14 +156,14 @@ public Response delete(@Parameter(description = "The id of the pipeline element schema = @Schema(implementation = DataSinkInvocation.class)) }, responseCode = "200", description = "The configured data sink invocation model"), }) - public Response getPipelineElementForTemplate( + public ResponseEntity getPipelineElementForTemplate( @Parameter(description = "The id of the pipeline element template", required = true) - @PathParam("id") String id, + @PathVariable("id") String id, @Parameter( description = "Overwrite the name and description of the pipeline element" + "with the labels given in the pipeline element template") - @QueryParam("overwriteNames") String overwriteNameAndDescription, + @RequestParam("overwriteNames") String overwriteNameAndDescription, @RequestBody(description = "The data sink invocation that should be configured with the template contents", content = @Content(schema = @Schema(implementation = DataSinkInvocation.class))) @@ -183,11 +173,10 @@ public Response getPipelineElementForTemplate( .applyTemplateOnPipelineElement()); } - @POST - @Path("{id}/processor") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized + @PostMapping( + path = "{id}/processor", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Configure a data processor with a pipeline element template.", tags = {"Pipeline Element Templates"}, responses = { @@ -197,13 +186,13 @@ public Response getPipelineElementForTemplate( schema = @Schema(implementation = DataProcessorInvocation.class)) }, responseCode = "200", description = "The configured data processor invocation model"), }) - public Response getPipelineElementForTemplate( + public ResponseEntity getPipelineElementForTemplate( @Parameter(description = "The id of the pipeline element template", required = true) - @PathParam("id") String id, + @PathVariable("id") String id, @Parameter(description = "Overwrite the name and description of the pipeline element with" + "the labels given in the pipeline element template") - @QueryParam("overwriteNames") String overwriteNameAndDescription, + @RequestParam("overwriteNames") String overwriteNameAndDescription, @RequestBody(description = "The data processor invocation that should be configured with the template contents", content = @Content(schema = @Schema(implementation = DataProcessorInvocation.class))) @@ -213,11 +202,10 @@ public Response getPipelineElementForTemplate( .applyTemplateOnPipelineElement()); } - @POST - @Path("{id}/adapter") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized + @PostMapping( + path = "{id}/adapter", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Configure an adapter with a pipeline element template.", tags = {"Pipeline Element Templates"}, responses = { @@ -227,13 +215,13 @@ public Response getPipelineElementForTemplate( schema = @Schema(implementation = AdapterDescription.class)) }, responseCode = "200", description = "The configured adapter model"), }) - public Response getPipelineElementForTemplate( + public ResponseEntity getPipelineElementForTemplate( @Parameter(description = "The id of the pipeline element template", required = true) - @PathParam("id") String id, + @PathVariable("id") String id, @Parameter(description = "Overwrite the name and description of the pipeline element" + "with the labels given in the pipeline element template") - @QueryParam("overwriteNames") String overwriteNameAndDescription, + @RequestParam("overwriteNames") String overwriteNameAndDescription, @RequestBody(description = "The adapter that should be configured with the template contents", content = @Content(schema = @Schema(implementation = AdapterDescription.class))) diff --git a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java b/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java index 8c28007a80..ad67e31047 100644 --- a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java +++ b/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractAuthGuardedRestResource.java @@ -15,6 +15,7 @@ * limitations under the License. * */ + package org.apache.streampipes.rest.core.base.impl; import org.apache.streampipes.model.client.user.Role; @@ -22,9 +23,6 @@ import org.springframework.security.core.context.SecurityContextHolder; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.SecurityContext; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -34,15 +32,13 @@ public class AbstractAuthGuardedRestResource extends AbstractRestResource { private static final List adminRoles = Arrays.asList( Role.Constants.ROLE_ADMIN_VALUE, Role.Constants.ROLE_SERVICE_ADMIN_VALUE); - @Context - protected SecurityContext securityContext; protected boolean isAuthenticated() { - return this.securityContext.getUserPrincipal() != null; + return SecurityContextHolder.getContext().getAuthentication() != null; } protected String getAuthenticatedUsername() { - return this.securityContext.getUserPrincipal().getName(); + return SecurityContextHolder.getContext().getAuthentication().getName(); } protected PrincipalUserDetails getPrincipal() { @@ -66,11 +62,10 @@ protected boolean hasAnyAuthority(String... authorities) { protected boolean hasAnyAuthority(List authorities) { return isAuthenticated() && SecurityContextHolder - .getContext() - .getAuthentication() - .getAuthorities() - .stream() - .anyMatch(a -> authorities.contains(a.getAuthority())); + .getContext() + .getAuthentication() + .getAuthorities() + .stream() + .anyMatch(a -> authorities.contains(a.getAuthority())); } - } diff --git a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractRestResource.java b/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractRestResource.java index 18ac8be032..e273dc3a20 100644 --- a/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractRestResource.java +++ b/streampipes-rest-core-base/src/main/java/org/apache/streampipes/rest/core/base/impl/AbstractRestResource.java @@ -38,15 +38,14 @@ import org.apache.streampipes.storage.management.StorageDispatcher; import org.apache.http.client.ClientProtocolException; - -import jakarta.ws.rs.core.Response; +import org.springframework.http.ResponseEntity; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; -public abstract class AbstractRestResource extends AbstractSharedRestInterface { +public class AbstractRestResource extends AbstractSharedRestInterface { protected ISpCoreConfigurationStorage getSpCoreConfigurationStorage() { return getNoSqlStorage().getSpCoreConfigurationStorage(); @@ -103,11 +102,11 @@ protected String parseURIContent(String payload, String mediaType) throws URISyn return HttpJsonParser.getContentFromUrl(uri, mediaType); } - protected Response constructSuccessMessage(Notification... notifications) { + protected ResponseEntity constructSuccessMessage(Notification... notifications) { return statusMessage(new SuccessMessage(notifications)); } - protected Response constructErrorMessage(Notification... notifications) { + protected ResponseEntity constructErrorMessage(Notification... notifications) { return statusMessage(new ErrorMessage(notifications)); } @@ -116,25 +115,17 @@ protected String decode(String encodedString) { return URLDecoder.decode(encodedString); } - protected Response statusMessage(Message message) { - return Response + protected ResponseEntity statusMessage(Message message) { + return ResponseEntity .ok() - .entity(message) - .build(); - } - - protected Response statusMessage(Message message, Response.ResponseBuilder builder) { - return builder - .entity(message) - .build(); + .body(message); } - protected Response unauthorized() { - return Response.status(Response.Status.UNAUTHORIZED).build(); + protected ResponseEntity unauthorized() { + return ResponseEntity.status(org.springframework.http.HttpStatus.UNAUTHORIZED).build(); } protected SpResourceManager getSpResourceManager() { return new SpResourceManager(); } - } diff --git a/streampipes-rest-extensions/pom.xml b/streampipes-rest-extensions/pom.xml index ec07d78fb6..80df122a1b 100644 --- a/streampipes-rest-extensions/pom.xml +++ b/streampipes-rest-extensions/pom.xml @@ -53,10 +53,6 @@ io.swagger.core.v3 swagger-annotations-jakarta - - jakarta.ws.rs - jakarta.ws.rs-api - org.rendersnake diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/AbstractExtensionsResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/AbstractExtensionsResource.java index 9854c20420..95dbbaad15 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/AbstractExtensionsResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/AbstractExtensionsResource.java @@ -19,42 +19,19 @@ package org.apache.streampipes.rest.extensions; import org.apache.http.HttpStatus; - -import jakarta.ws.rs.core.Response; +import org.springframework.http.ResponseEntity; public class AbstractExtensionsResource { - protected Response ok(T entity) { - return Response + protected ResponseEntity ok(T entity) { + return ResponseEntity .ok() - .entity(entity) - .build(); - } - - protected Response clientError() { - return Response - .status(HttpStatus.SC_BAD_REQUEST) - .build(); + .body(entity); } - protected Response serverError() { - return Response + protected ResponseEntity serverError() { + return ResponseEntity .status(HttpStatus.SC_INTERNAL_SERVER_ERROR) .build(); } - - protected Response notModified(T entity) { - return Response - .notModified() - .entity(entity) - .build(); - } - - protected Response noContent(T entity) { - return Response - .noContent() - .entity(entity) - .build(); - } - } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/AbstractPipelineElementResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/AbstractPipelineElementResource.java index 4ff9621ab1..e2bd86a454 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/AbstractPipelineElementResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/AbstractPipelineElementResource.java @@ -28,21 +28,16 @@ import org.apache.streampipes.model.grounding.EventGrounding; import org.apache.streampipes.model.grounding.TransportFormat; import org.apache.streampipes.model.grounding.TransportProtocol; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; -import org.apache.streampipes.rest.shared.util.SpMediaType; import com.google.common.base.Charsets; import com.google.common.io.Resources; import org.apache.http.HttpStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import java.io.IOException; import java.net.URL; @@ -59,18 +54,13 @@ public abstract class AbstractPipelineElementResource< private static final Logger LOG = LoggerFactory.getLogger(AbstractPipelineElementResource.class); - @GET - @Path("{appId}") - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public NamedStreamPipesEntity getDescription(@PathParam("appId") String appId) { + @GetMapping(path = "{appId}", produces = MediaType.APPLICATION_JSON_VALUE) + public NamedStreamPipesEntity getDescription(@PathVariable("appId") String appId) { return prepareElement(appId); } - @GET - @Path("{appId}/assets") - @Produces(SpMediaType.APPLICATION_ZIP) - public Response getAssets(@PathParam("appId") String appId) { + @GetMapping(path = "{appId}/assets", produces = "application/zip") + public ResponseEntity getAssets(@PathVariable("appId") String appId) { List includedAssets = getDeclarerById(appId).declareConfig().getDescription().getIncludedAssets(); try { return ok(new AssetZipGenerator(appId, includedAssets).makeZip()); @@ -80,29 +70,25 @@ public Response getAssets(@PathParam("appId") String appId) { } } - @GET - @Path("{appId}/assets/icon") - @Produces("image/png") - public Response getIconAsset(@PathParam("appId") String appId) throws IOException { + @GetMapping(path = "{appId}/assets/icon", produces = MediaType.IMAGE_PNG_VALUE) + public ResponseEntity getIconAsset(@PathVariable("appId") String appId) throws IOException { try { URL iconUrl = Resources.getResource(makeIconPath(appId)); return ok(Resources.toByteArray(iconUrl)); } catch (IllegalArgumentException e) { LOG.warn("No icon resource found for pipeline element {}", appId); - return Response.status(HttpStatus.SC_BAD_REQUEST).build(); + return ResponseEntity.status(HttpStatus.SC_BAD_REQUEST).build(); } } - @GET - @Path("{id}/assets/documentation") - @Produces(MediaType.TEXT_PLAIN) - public Response getDocumentationAsset(@PathParam("id") String elementId) throws IOException { + @GetMapping(path = "{id}/assets/documentation", produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity getDocumentationAsset(@PathVariable("id") String elementId) throws IOException { try { URL documentationUrl = Resources.getResource(makeDocumentationPath(elementId)); return ok(Resources.toString(documentationUrl, Charsets.UTF_8)); } catch (IllegalArgumentException e) { LOG.warn("No documentation resource found for pipeline element {}", elementId); - return Response.status(HttpStatus.SC_BAD_REQUEST).build(); + return ResponseEntity.status(HttpStatus.SC_BAD_REQUEST).build(); } } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/WelcomePage.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/WelcomePage.java index 38867a73af..aa9454b5f3 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/WelcomePage.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/WelcomePage.java @@ -25,26 +25,25 @@ import org.apache.streampipes.rest.extensions.html.JSONGenerator; import org.apache.streampipes.rest.extensions.html.page.WelcomePageGenerator; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.Collection; -@Path("/") +@RestController +@RequestMapping("/") public class WelcomePage { - @GET - @Produces(MediaType.TEXT_HTML) + @GetMapping(produces = MediaType.TEXT_HTML_VALUE) public String getWelcomePageHtml() { WelcomePageGenerator welcomePage = getWelcomePageGenerator(); HTMLGenerator html = new HTMLGenerator(welcomePage.buildUris()); return html.buildHtml(); } - @GET - @Produces(MediaType.APPLICATION_JSON) + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) public String getWelcomePageJson() { WelcomePageGenerator welcomePage = getWelcomePageGenerator(); JSONGenerator json = new JSONGenerator(welcomePage.buildUris()); diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterAssetResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterAssetResource.java index b47338c927..0fb89bfc1c 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterAssetResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterAssetResource.java @@ -22,23 +22,26 @@ import org.apache.streampipes.extensions.management.connect.ConnectWorkerDescriptionProvider; import org.apache.streampipes.extensions.management.util.AssetsUtil; import org.apache.streampipes.model.connect.adapter.AdapterDescription; +import org.apache.streampipes.model.message.Notifications; +import org.apache.streampipes.rest.shared.exception.SpMessageException; import org.apache.streampipes.rest.shared.impl.AbstractSharedRestInterface; import com.google.common.base.Charsets; import com.google.common.io.Resources; - -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.net.URL; import java.util.Optional; -@Path("/api/v1/worker/adapters") +@RestController +@RequestMapping("/api/v1/worker/adapters") public class AdapterAssetResource extends AbstractSharedRestInterface { private ConnectWorkerDescriptionProvider connectWorkerDescriptionProvider; @@ -48,36 +51,31 @@ public AdapterAssetResource() { } - @GET - @Path("/{id}/assets") - @Produces("application/zip") - public Response getAssets(@PathParam("id") String id) { + @GetMapping(path = "/{id}/assets", produces = "application/zip") + public ResponseEntity getAssets(@PathVariable("id") String id) { Optional adapterDescription = this.connectWorkerDescriptionProvider.getAdapterDescription(id); if (adapterDescription.isPresent()) { try { return ok(new AssetZipGenerator(id, adapterDescription.get().getIncludedAssets()).makeZip()); } catch (IOException e) { - e.printStackTrace(); - return fail(); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } else { - return fail(); + throw new SpMessageException( + HttpStatus.NOT_FOUND, + Notifications.error(String.format("Could not find adapter with id %s", id))); } } - @GET - @Path("/{id}/assets/icon") - @Produces("image/png") - public Response getIconAsset(@PathParam("id") String elementId) throws IOException { + @GetMapping(path = "/{id}/assets/icon", produces = MediaType.IMAGE_PNG_VALUE) + public ResponseEntity getIconAsset(@PathVariable("id") String elementId) throws IOException { URL iconUrl = Resources.getResource(AssetsUtil.makeIconPath(elementId)); return ok(Resources.toByteArray(iconUrl)); } - @GET - @Path("/{id}/assets/documentation") - @Produces(MediaType.TEXT_PLAIN) - public String getDocumentationAsset(@PathParam("id") String elementId) throws IOException { + @GetMapping(path = "/{id}/assets/documentation", produces = MediaType.TEXT_PLAIN_VALUE) + public String getDocumentationAsset(@PathVariable("id") String elementId) throws IOException { URL documentationUrl = Resources.getResource(AssetsUtil.makeDocumentationPath(elementId)); return Resources.toString(documentationUrl, Charsets.UTF_8); } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterDescriptionResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterDescriptionResource.java index cdc0f75146..6df779c15b 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterDescriptionResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterDescriptionResource.java @@ -21,26 +21,26 @@ import org.apache.streampipes.extensions.management.init.DeclarersSingleton; import org.apache.streampipes.extensions.management.locales.LabelGenerator; import org.apache.streampipes.model.connect.adapter.AdapterDescription; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; +import org.apache.streampipes.model.message.Notifications; +import org.apache.streampipes.rest.shared.exception.SpMessageException; import org.apache.streampipes.rest.shared.impl.AbstractSharedRestInterface; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.io.IOException; -@Path("/api/v1/worker/adapters") +@RestController +@RequestMapping("/api/v1/worker/adapters") public class AdapterDescriptionResource extends AbstractSharedRestInterface { - @GET - @Path("/{id}") - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response getAdapterDescription(@PathParam("id") String id) { + @GetMapping(path = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getAdapterDescription(@PathVariable("id") String id) { var adapterDescriptionOpt = DeclarersSingleton.getInstance().getAdapter(id); if (adapterDescriptionOpt.isPresent()) { try { @@ -48,10 +48,12 @@ public Response getAdapterDescription(@PathParam("id") String id) { var localizedDescription = applyLocales(adapterDescription); return ok(localizedDescription); } catch (IOException e) { - return serverError(e); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } else { - return notFound(); + throw new SpMessageException( + HttpStatus.NOT_FOUND, + Notifications.error(String.format("Could not find adapter with id %s", id))); } } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterWorkerResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterWorkerResource.java index 56475c355d..8b61e0c2e7 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterWorkerResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/AdapterWorkerResource.java @@ -24,23 +24,26 @@ import org.apache.streampipes.extensions.management.init.RunningAdapterInstances; import org.apache.streampipes.model.connect.adapter.AdapterDescription; import org.apache.streampipes.model.message.Notifications; +import org.apache.streampipes.model.message.SuccessMessage; import org.apache.streampipes.model.monitoring.SpLogMessage; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; +import org.apache.streampipes.rest.shared.exception.SpLogMessageException; import org.apache.streampipes.rest.shared.impl.AbstractSharedRestInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - - -@Path("/api/v1/worker") +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collection; + +@RestController +@RequestMapping("/api/v1/worker") public class AdapterWorkerResource extends AbstractSharedRestInterface { private static final Logger logger = LoggerFactory.getLogger(AdapterWorkerResource.class); @@ -58,21 +61,17 @@ public AdapterWorkerResource(AdapterWorkerManagement adapterManagement) { this.adapterManagement = adapterManagement; } - @GET - @JacksonSerialized - @Path("/running") - @Produces(MediaType.APPLICATION_JSON) - public Response getRunningAdapterInstances() { + @GetMapping(path = "/running", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getRunningAdapterInstances() { return ok(adapterManagement.getAllRunningAdapterInstances()); } - @POST - @JacksonSerialized - @Path("/stream/invoke") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response invokeAdapter(AdapterDescription adapterStreamDescription) { + @PostMapping( + path = "/stream/invoke", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity invokeAdapter(@RequestBody AdapterDescription adapterStreamDescription) { try { adapterManagement.invokeAdapter(adapterStreamDescription); @@ -83,16 +82,15 @@ public Response invokeAdapter(AdapterDescription adapterStreamDescription) { return ok(Notifications.success(responseMessage)); } catch (AdapterException e) { logger.error("Error while starting adapter with id " + adapterStreamDescription.getElementId(), e); - return serverError(SpLogMessage.from(e)); + throw new SpLogMessageException(HttpStatus.INTERNAL_SERVER_ERROR, SpLogMessage.from(e)); } } - @POST - @JacksonSerialized - @Path("/stream/stop") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response stopAdapter(AdapterDescription adapterStreamDescription) { + @PostMapping( + path = "/stream/stop", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity stopAdapter(@RequestBody AdapterDescription adapterStreamDescription) { String responseMessage; try { @@ -107,7 +105,7 @@ public Response stopAdapter(AdapterDescription adapterStreamDescription) { return ok(Notifications.success(responseMessage)); } catch (AdapterException e) { logger.error("Error while stopping adapter with id " + adapterStreamDescription.getElementId(), e); - return serverError(SpLogMessage.from(e)); + throw new SpLogMessageException(HttpStatus.INTERNAL_SERVER_ERROR, SpLogMessage.from(e)); } } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/GuessResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/GuessResource.java index e00102437b..25adc18edc 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/GuessResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/GuessResource.java @@ -24,20 +24,21 @@ import org.apache.streampipes.extensions.management.context.AdapterContextGenerator; import org.apache.streampipes.model.connect.adapter.AdapterDescription; import org.apache.streampipes.model.connect.guess.GuessSchema; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; +import org.apache.streampipes.rest.shared.exception.SpMessageException; import org.apache.streampipes.rest.shared.impl.AbstractSharedRestInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - - -@Path("/api/v1/worker/guess") +@RestController +@RequestMapping("/api/v1/worker/guess") public class GuessResource extends AbstractSharedRestInterface { private static final Logger logger = LoggerFactory.getLogger(GuessResource.class); @@ -52,11 +53,11 @@ public GuessResource(GuessManagement guessManagement) { this.guessManagement = guessManagement; } - @POST - @JacksonSerialized - @Path("/schema") - @Produces(MediaType.APPLICATION_JSON) - public Response guessSchema(AdapterDescription adapterDescription) { + @PostMapping( + path = "/schema", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity guessSchema(@RequestBody AdapterDescription adapterDescription) { try { GuessSchema result = guessManagement.guessSchema(adapterDescription); @@ -64,11 +65,11 @@ public Response guessSchema(AdapterDescription adapterDescription) { return ok(result); } catch (ParseException e) { logger.error("Error while parsing events: ", e); - return serverError(e); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } catch (AdapterException e) { logger.error("Error while guessing schema for AdapterDescription: {}, {}", adapterDescription.getElementId(), e.getMessage()); - return serverError(e); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/HttpServerAdapterResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/HttpServerAdapterResource.java index 70fea2aa42..4fe4911a64 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/HttpServerAdapterResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/HttpServerAdapterResource.java @@ -18,27 +18,29 @@ package org.apache.streampipes.rest.extensions.connect; import org.apache.streampipes.extensions.management.connect.HttpServerAdapterManagement; +import org.apache.streampipes.rest.shared.exception.SpMessageException; -import org.apache.http.HttpStatus; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.core.Response; - -@Path("/api/v1/worker/live") +@RestController +@RequestMapping("/api/v1/worker/live") public class HttpServerAdapterResource { - @POST - @Path("{endpointId}") - public Response receiveEvent(@PathParam("endpointId") String endpointId, - byte[] body) { + @PostMapping(path = "{endpointId}") + public ResponseEntity receiveEvent(@PathVariable("endpointId") String endpointId, + @RequestBody byte[] body) { try { HttpServerAdapterManagement.INSTANCE.notify(endpointId, body); - return Response.ok().build(); + return ResponseEntity.ok().build(); } catch (Exception e) { - return Response.status(HttpStatus.SC_BAD_REQUEST).entity(e.getMessage()).build(); + throw new SpMessageException(HttpStatus.BAD_REQUEST, e); } } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/RuntimeResolvableResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/RuntimeResolvableResource.java index a49616c66b..0412560c99 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/RuntimeResolvableResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/connect/RuntimeResolvableResource.java @@ -26,29 +26,27 @@ import org.apache.streampipes.extensions.management.connect.RuntimeResovable; import org.apache.streampipes.model.runtime.RuntimeOptionsRequest; import org.apache.streampipes.model.runtime.RuntimeOptionsResponse; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; import org.apache.streampipes.rest.shared.impl.AbstractSharedRestInterface; -import org.apache.http.HttpStatus; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -@Path("/api/v1/worker/resolvable") +@RestController +@RequestMapping("/api/v1/worker/resolvable") public class RuntimeResolvableResource extends AbstractSharedRestInterface { - @POST - @Path("{id}/configurations") - @JacksonSerialized - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response fetchConfigurations(@PathParam("id") String elementId, - RuntimeOptionsRequest runtimeOptionsRequest) { + @PostMapping( + path = "{id}/configurations", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity fetchConfigurations(@PathVariable("id") String elementId, + @RequestBody RuntimeOptionsRequest runtimeOptionsRequest) { var adapter = RuntimeResovable.getAdapter(elementId); RuntimeOptionsResponse response; @@ -66,10 +64,9 @@ public Response fetchConfigurations(@PathParam("id") String elementId, "This element does not support dynamic options - is the pipeline element description up to date?"); } } catch (SpConfigurationException e) { - return jakarta.ws.rs.core.Response - .status(HttpStatus.SC_BAD_REQUEST) - .entity(e) - .build(); + return ResponseEntity + .status(HttpStatus.BAD_REQUEST) + .body(e); } } } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/AdapterMigrationResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/AdapterMigrationResource.java index 476f11b64b..1ed5d319ef 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/AdapterMigrationResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/AdapterMigrationResource.java @@ -22,7 +22,7 @@ import org.apache.streampipes.extensions.api.migration.IAdapterMigrator; import org.apache.streampipes.model.connect.adapter.AdapterDescription; import org.apache.streampipes.model.extensions.migration.MigrationRequest; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; +import org.apache.streampipes.model.migration.MigrationResult; import org.apache.streampipes.sdk.extractor.StaticPropertyExtractor; import io.swagger.v3.oas.annotations.Operation; @@ -30,30 +30,30 @@ import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import org.apache.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -@Path("/api/v1/migrations/adapter") +@RestController +@RequestMapping("/api/v1/migrations/adapter") public class AdapterMigrationResource extends MigrateExtensionsResource< AdapterDescription, IStaticPropertyExtractor, IAdapterMigrator > { - @POST - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized + @PostMapping( + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) @Operation( summary = "Execute the migration for a specific adapter instance", tags = {"Extensions", "Migration"}, responses = { @ApiResponse( - responseCode = "" + HttpStatus.SC_OK, + responseCode = "200", description = "The migration was executed. Its result is described in the response. " + "The Response needs to be handled accordingly.", content = @Content( @@ -61,12 +61,12 @@ public class AdapterMigrationResource extends MigrateExtensionsResource< name = "Successful migration", value = "{\"success\": true,\"messages\": \"SUCCESS\", \"element\": {}}" ), - mediaType = MediaType.APPLICATION_JSON + mediaType = MediaType.APPLICATION_JSON_VALUE ) ) } ) - public Response migrateAdapter( + public ResponseEntity> migrateAdapter( @Parameter( description = "request that encompasses the adapter description(AdapterDescription) and " + "the configuration of the migration", @@ -74,7 +74,7 @@ public Response migrateAdapter( + "\"modelType\": \"adapter\", \"fromVersion\": 0, \"toVersion\": 1}}", required = true ) - MigrationRequest adapterMigrationRequest) { + @RequestBody MigrationRequest adapterMigrationRequest) { return ok(handleMigration(adapterMigrationRequest)); } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/DataProcessorMigrationResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/DataProcessorMigrationResource.java index 8a493a6e08..c062679949 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/DataProcessorMigrationResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/DataProcessorMigrationResource.java @@ -22,7 +22,7 @@ import org.apache.streampipes.extensions.api.migration.IDataProcessorMigrator; import org.apache.streampipes.model.extensions.migration.MigrationRequest; import org.apache.streampipes.model.graph.DataProcessorInvocation; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; +import org.apache.streampipes.model.migration.MigrationResult; import org.apache.streampipes.sdk.extractor.ProcessingElementParameterExtractor; import io.swagger.v3.oas.annotations.Operation; @@ -31,23 +31,24 @@ import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.apache.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -@Path("api/v1/migrations/processor") +@RestController +@RequestMapping("api/v1/migrations/processor") public class DataProcessorMigrationResource extends MigrateExtensionsResource< DataProcessorInvocation, IDataProcessorParameterExtractor, IDataProcessorMigrator > { - @POST - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized + @PostMapping( + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) @Operation( summary = "Execute the migration for a specific data processor instance", tags = {"Extensions", "Migration"}, responses = { @@ -60,12 +61,12 @@ public class DataProcessorMigrationResource extends MigrateExtensionsResource< name = "Successful migration", value = "{\"success\": true,\"messages\": \"SUCCESS\", \"element\": {}}" ), - mediaType = MediaType.APPLICATION_JSON + mediaType = MediaType.APPLICATION_JSON_VALUE ) ) } ) - public Response migrateDataProcessor( + public ResponseEntity> migrateDataProcessor( @Parameter( description = "Request that encompasses the data processor description (DataProcessorInvocation) and " + "the configuration of the migration to be performed", @@ -73,7 +74,7 @@ public Response migrateDataProcessor( + "\"modelType\": \"dprocessor\", \"fromVersion\": 0, \"toVersion\": 1}}", required = true ) - MigrationRequest processorMigrationRequest) { + @RequestBody MigrationRequest processorMigrationRequest) { return ok(handleMigration(processorMigrationRequest)); } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/DataSinkMigrationResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/DataSinkMigrationResource.java index 397fce7b49..2ca9ac2771 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/DataSinkMigrationResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/migration/DataSinkMigrationResource.java @@ -22,7 +22,7 @@ import org.apache.streampipes.extensions.api.migration.IDataSinkMigrator; import org.apache.streampipes.model.extensions.migration.MigrationRequest; import org.apache.streampipes.model.graph.DataSinkInvocation; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; +import org.apache.streampipes.model.migration.MigrationResult; import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor; @@ -32,49 +32,50 @@ import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.apache.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - - -@Path("api/v1/migrations/sink") +@RestController +@RequestMapping("/api/v1/migrations/sink") public class DataSinkMigrationResource extends MigrateExtensionsResource< - DataSinkInvocation, - IDataSinkParameterExtractor, + DataSinkInvocation, + IDataSinkParameterExtractor, IDataSinkMigrator - > { - @POST - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized + > { + @PostMapping( + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE + ) @Operation( - summary = "Execute the migration for a specific data sink instance", tags = {"Extensions", "Migration"}, - responses = { - @ApiResponse( - responseCode = "" + HttpStatus.SC_OK, - description = "The migration was executed. It's result is described in the response. " - + "The Response needs to be handled accordingly.", - content = @Content( - examples = @ExampleObject( - name = "Successful migration", - value = "{\"success\": true,\"messages\": \"SUCCESS\", \"element\": {}}" - ), - mediaType = MediaType.APPLICATION_JSON - ) + summary = "Execute the migration for a specific data sink instance", tags = {"Extensions", "Migration"}, + responses = { + @ApiResponse( + responseCode = "" + HttpStatus.SC_OK, + description = "The migration was executed. It's result is described in the response. " + + "The Response needs to be handled accordingly.", + content = @Content( + examples = @ExampleObject( + name = "Successful migration", + value = "{\"success\": true,\"messages\": \"SUCCESS\", \"element\": {}}" + ), + mediaType = MediaType.APPLICATION_JSON_VALUE ) - } - ) - public Response migrateDataSink( - @Parameter( - description = "Request that encompasses the data sink description (DataSinkInvocation) and " - + "the configuration of the migration to be performed", - example = "{\"migrationElement\": {}, \"modelMigratorConfig\": {\"targetAppId\": \"app-id\", " - + "\"modelType\": \"dsink\", \"fromVersion\": 0, \"toVersion\": 1}}", - required = true ) - MigrationRequest sinkMigrationRequest) { + } + ) + public ResponseEntity> migrateDataSink( + @Parameter( + description = "Request that encompasses the data sink description (DataSinkInvocation) and " + + "the configuration of the migration to be performed", + example = "{\"migrationElement\": {}, \"modelMigratorConfig\": {\"targetAppId\": \"app-id\", " + + "\"modelType\": \"dsink\", \"fromVersion\": 0, \"toVersion\": 1}}", + required = true + ) + @RequestBody MigrationRequest sinkMigrationRequest) { return ok(handleMigration(sinkMigrationRequest)); } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/monitoring/MonitoringResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/monitoring/MonitoringResource.java index 8cfbea34d4..e907dae6c3 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/monitoring/MonitoringResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/monitoring/MonitoringResource.java @@ -20,20 +20,21 @@ package org.apache.streampipes.rest.extensions.monitoring; import org.apache.streampipes.extensions.api.monitoring.SpMonitoringManager; +import org.apache.streampipes.model.monitoring.SpEndpointMonitoringInfo; import org.apache.streampipes.rest.extensions.AbstractExtensionsResource; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -@Path("monitoring") +@RestController +@RequestMapping("monitoring") public class MonitoringResource extends AbstractExtensionsResource { - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getMonitoringInfos() { + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getMonitoringInfos() { try { return ok(SpMonitoringManager.INSTANCE.getMonitoringInfo()); } finally { diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/DataProcessorPipelineElementResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/DataProcessorPipelineElementResource.java index b583f3c51c..2ce81664c5 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/DataProcessorPipelineElementResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/DataProcessorPipelineElementResource.java @@ -30,11 +30,13 @@ import org.apache.streampipes.sdk.extractor.ProcessingElementParameterExtractor; import org.apache.streampipes.svcdiscovery.api.model.SpServicePathPrefix; -import jakarta.ws.rs.Path; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.Map; -@Path(SpServicePathPrefix.DATA_PROCESSOR) +@RestController +@RequestMapping(SpServicePathPrefix.DATA_PROCESSOR) public class DataProcessorPipelineElementResource extends InvocablePipelineElementResource< DataProcessorInvocation, IStreamPipesDataProcessor, diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/DataSinkPipelineElementResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/DataSinkPipelineElementResource.java index 9b525fd14d..3c4127085f 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/DataSinkPipelineElementResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/DataSinkPipelineElementResource.java @@ -30,11 +30,13 @@ import org.apache.streampipes.sdk.extractor.DataSinkParameterExtractor; import org.apache.streampipes.svcdiscovery.api.model.SpServicePathPrefix; -import jakarta.ws.rs.Path; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.Map; -@Path(SpServicePathPrefix.DATA_SINK) +@RestController +@RequestMapping(SpServicePathPrefix.DATA_SINK) public class DataSinkPipelineElementResource extends InvocablePipelineElementResource { @Override @@ -42,17 +43,15 @@ protected Map getElementDeclarers() { return DeclarersSingleton.getInstance().getDataStreams(); } - @GET - @Path("{streamId}/assets") - @Produces("application/zip") - public jakarta.ws.rs.core.Response getAssets(@PathParam("streamId") String streamId) { + @GetMapping(path = "{streamId}/assets", produces = "application/zip") + public ResponseEntity getAssets(@PathVariable("streamId") String streamId) { try { return ok(new AssetZipGenerator(streamId, getById(streamId) .getIncludedAssets()).makeZip()); } catch (IOException e) { e.printStackTrace(); - return jakarta.ws.rs.core.Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).build(); + return ResponseEntity.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).build(); } } diff --git a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/InvocablePipelineElementResource.java b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/InvocablePipelineElementResource.java index 61e866db90..3f7e160970 100644 --- a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/InvocablePipelineElementResource.java +++ b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/pe/InvocablePipelineElementResource.java @@ -35,22 +35,20 @@ import org.apache.streampipes.model.runtime.RuntimeOptionsRequest; import org.apache.streampipes.model.runtime.RuntimeOptionsResponse; import org.apache.streampipes.rest.extensions.AbstractPipelineElementResource; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; import org.apache.streampipes.sdk.extractor.AbstractParameterExtractor; import org.apache.http.HttpStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; - +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; import java.util.Map; public abstract class InvocablePipelineElementResource< @@ -71,13 +69,12 @@ public InvocablePipelineElementResource(Class clazz) { protected abstract String getInstanceId(String uri, String elementId); - @POST - @Path("{elementId}") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized - public jakarta.ws.rs.core.Response invokeRuntime(@PathParam("elementId") String elementId, - K graph) { + @PostMapping( + path = "{elementId}", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity invokeRuntime(@PathVariable("elementId") String elementId, + @RequestBody K graph) { if (isDebug()) { LOG.info("SP_DEBUG env variable is set - overriding broker hostname and port for local development"); @@ -109,13 +106,12 @@ public jakarta.ws.rs.core.Response invokeRuntime(@PathParam("elementId") String return ok(new Response(elementId, false, "Could not find the element with id: " + elementId)); } - @POST - @Path("{elementId}/configurations") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized - public jakarta.ws.rs.core.Response fetchConfigurations(@PathParam("elementId") String elementId, - RuntimeOptionsRequest req) { + @PostMapping( + path = "{elementId}/configurations", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity fetchConfigurations(@PathVariable("elementId") String elementId, + @RequestBody RuntimeOptionsRequest req) { T declarer = getDeclarerById(elementId); RuntimeOptionsResponse responseOptions; @@ -131,23 +127,21 @@ public jakarta.ws.rs.core.Response fetchConfigurations(@PathParam("elementId") S new RuntimeResolvableRequestHandler().handleRuntimeResponse((SupportsRuntimeConfig) declarer, req); return ok(responseOptions); } else { - return jakarta.ws.rs.core.Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).build(); + return ResponseEntity.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).build(); } } catch (SpConfigurationException e) { - return jakarta.ws.rs.core.Response + return ResponseEntity .status(HttpStatus.SC_BAD_REQUEST) - .entity(e) - .build(); + .body(e); } } - @POST - @Path("{elementId}/output") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized - public jakarta.ws.rs.core.Response fetchOutputStrategy(@PathParam("elementId") String elementId, - K runtimeOptionsRequest) { + @PostMapping( + path = "{elementId}/output", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity fetchOutputStrategy(@PathVariable("elementId") String elementId, + @RequestBody K runtimeOptionsRequest) { try { //I runtimeOptionsRequest = JacksonSerializer.getObjectMapper().readValue(payload, clazz); ResolvesContainerProvidedOutputStrategy resolvesOutput = @@ -163,11 +157,9 @@ public jakarta.ws.rs.core.Response fetchOutputStrategy(@PathParam("elementId") S // TODO move endpoint to /elementId/instances/runningInstanceId - @DELETE - @Path("{elementId}/{runningInstanceId}") - @Produces(MediaType.APPLICATION_JSON) - public jakarta.ws.rs.core.Response detach(@PathParam("elementId") String elementId, - @PathParam("runningInstanceId") String runningInstanceId) { + @DeleteMapping(path = "{elementId}/{runningInstanceId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity detach(@PathVariable("elementId") String elementId, + @PathVariable("runningInstanceId") String runningInstanceId) { IStreamPipesRuntime runningInstance = RunningInstances.INSTANCE.getInvocation(runningInstanceId); @@ -184,10 +176,8 @@ public jakarta.ws.rs.core.Response detach(@PathParam("elementId") String element return ok(new Response(elementId, false, "Could not find the running instance with id: " + runningInstanceId)); } - @GET - @Path("{elementId}/instances") - @Produces(MediaType.APPLICATION_JSON) - public jakarta.ws.rs.core.Response listRunningInstances(@PathParam("elementId") String elementId) { + @GetMapping(path = "{elementId}/instances", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> listRunningInstances(@PathVariable("elementId") String elementId) { return ok(RunningInstances.INSTANCE.getRunningInstanceIdsForElement(elementId)); } diff --git a/streampipes-rest-shared/pom.xml b/streampipes-rest-shared/pom.xml index a2f50afb17..e40097cb19 100644 --- a/streampipes-rest-shared/pom.xml +++ b/streampipes-rest-shared/pom.xml @@ -48,45 +48,8 @@ - jakarta.annotation - jakarta.annotation-api - - - jakarta.servlet - jakarta.servlet-api - - - jakarta.ws.rs - jakarta.ws.rs-api - - - org.glassfish.jersey.media - jersey-media-multipart - - - org.apache.httpcomponents - httpcore - - - - - org.glassfish.jersey.containers - jersey-container-jetty-http - - - org.eclipse.jetty - jetty-server - - - org.eclipse.jetty - jetty-util - - - org.eclipse.jetty - jetty-continuation - - - test + org.springframework.boot + spring-boot-starter-web junit diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/annotation/NoAuthenticationRequired.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/annotation/NoAuthenticationRequired.java deleted file mode 100644 index e790c93cbd..0000000000 --- a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/annotation/NoAuthenticationRequired.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.apache.streampipes.rest.shared.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface NoAuthenticationRequired { -} diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/RestResponseExceptionHandler.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/RestResponseExceptionHandler.java new file mode 100644 index 0000000000..6ed9eb175d --- /dev/null +++ b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/RestResponseExceptionHandler.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.streampipes.rest.shared.exception; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@ControllerAdvice +public class RestResponseExceptionHandler extends ResponseEntityExceptionHandler { + + @ExceptionHandler(value = { SpNotificationException.class }) + protected ResponseEntity handleException( + RuntimeException ex, WebRequest request) { + var notificationException = (SpNotificationException) ex; + return ResponseEntity + .status(notificationException.getStatus()) + .body(notificationException.getNotification()); + } +} diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/RestResponseLogMessageExceptionHandler.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/RestResponseLogMessageExceptionHandler.java new file mode 100644 index 0000000000..97c3d5beaf --- /dev/null +++ b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/RestResponseLogMessageExceptionHandler.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.streampipes.rest.shared.exception; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@ControllerAdvice +public class RestResponseLogMessageExceptionHandler extends ResponseEntityExceptionHandler { + + @ExceptionHandler(value = {SpLogMessageException.class}) + protected ResponseEntity handleException( + RuntimeException ex, WebRequest request) { + var exception = (SpLogMessageException) ex; + return ResponseEntity + .status(exception.getStatus()) + .body(exception.getSpMessage()); + } +} diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/RestResponseMessageExceptionHandler.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/RestResponseMessageExceptionHandler.java new file mode 100644 index 0000000000..e7044ea9a9 --- /dev/null +++ b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/RestResponseMessageExceptionHandler.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.streampipes.rest.shared.exception; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@ControllerAdvice +public class RestResponseMessageExceptionHandler extends ResponseEntityExceptionHandler { + + @ExceptionHandler(value = { SpMessageException.class }) + protected ResponseEntity handleException( + RuntimeException ex, WebRequest request) { + var messageException = (SpMessageException) ex; + return ResponseEntity + .status(messageException.getStatus()) + .body(messageException.getSpMessage()); + } +} + diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/api/CRUDResource.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/SpLogMessageException.java similarity index 58% rename from streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/api/CRUDResource.java rename to streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/SpLogMessageException.java index 16529041ec..c1fa115a73 100644 --- a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/api/CRUDResource.java +++ b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/SpLogMessageException.java @@ -15,19 +15,29 @@ * limitations under the License. * */ -package org.apache.streampipes.rest.shared.api; -import jakarta.ws.rs.core.Response; +package org.apache.streampipes.rest.shared.exception; -public interface CRUDResource { +import org.apache.streampipes.model.monitoring.SpLogMessage; - Response getAll(); +import org.springframework.http.HttpStatus; - Response getById(K k); +public class SpLogMessageException extends RuntimeException { - Response create(V entity); + private final SpLogMessage message; + private final HttpStatus status; - Response update(K k, V entity); + public SpLogMessageException(HttpStatus status, + SpLogMessage message) { + this.status = status; + this.message = message; + } - Response delete(K k); + public SpLogMessage getSpMessage() { + return message; + } + + public HttpStatus getStatus() { + return status; + } } diff --git a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/SpMessageException.java similarity index 50% rename from streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java rename to streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/SpMessageException.java index 64c8f043bd..2ade1d0680 100644 --- a/streampipes-service-base/src/main/java/org/apache/streampipes/service/base/rest/BaseResourceConfig.java +++ b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/SpMessageException.java @@ -15,28 +15,36 @@ * limitations under the License. * */ -package org.apache.streampipes.service.base.rest; -import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.server.ServerProperties; +package org.apache.streampipes.rest.shared.exception; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import org.apache.streampipes.model.message.Message; +import org.apache.streampipes.model.message.Notifications; -public abstract class BaseResourceConfig extends ResourceConfig { +import org.springframework.http.HttpStatus; - public BaseResourceConfig() { - var customConfigs = new HashMap(); - addAdditionalConfigs(customConfigs); - property(ServerProperties.WADL_FEATURE_DISABLE, true); - addProperties(customConfigs); - getClassesToRegister().forEach(this::register); +public class SpMessageException extends RuntimeException { + private final Message message; + private final HttpStatus status; + + public SpMessageException(HttpStatus status, + Message message) { + this.status = status; + this.message = message; } - public abstract Set> getClassesToRegister(); + public SpMessageException(HttpStatus status, + Throwable throwable) { + this.status = status; + this.message = Notifications.error(throwable.getMessage()); + } - public abstract void addAdditionalConfigs(Map configs); + public Message getSpMessage() { + return message; + } + public HttpStatus getStatus() { + return status; + } } diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/annotation/JacksonSerialized.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/SpNotificationException.java similarity index 56% rename from streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/annotation/JacksonSerialized.java rename to streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/SpNotificationException.java index 293cbdd4e7..77a885ecfe 100644 --- a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/annotation/JacksonSerialized.java +++ b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/exception/SpNotificationException.java @@ -15,17 +15,30 @@ * limitations under the License. * */ -package org.apache.streampipes.rest.shared.annotation; -import jakarta.ws.rs.NameBinding; +package org.apache.streampipes.rest.shared.exception; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -@NameBinding -@Target({ElementType.TYPE, ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface JacksonSerialized { +import org.apache.streampipes.model.message.Notification; + +import org.springframework.http.HttpStatus; + +public class SpNotificationException extends RuntimeException { + + private final Notification notification; + private final HttpStatus status; + + public SpNotificationException(HttpStatus status, + Notification notification) { + this.status = status; + this.notification = notification; + } + + public Notification getNotification() { + return notification; + } + + public HttpStatus getStatus() { + return status; + } } diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/impl/AbstractSharedRestInterface.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/impl/AbstractSharedRestInterface.java index 17410a154f..2c7c994e4d 100644 --- a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/impl/AbstractSharedRestInterface.java +++ b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/impl/AbstractSharedRestInterface.java @@ -17,55 +17,52 @@ */ package org.apache.streampipes.rest.shared.impl; -import org.apache.http.HttpStatus; - -import jakarta.ws.rs.core.Response; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; public abstract class AbstractSharedRestInterface { - protected Response ok(T entity) { - return Response - .ok(entity) - .build(); + protected ResponseEntity ok(T entity) { + return ResponseEntity + .ok(entity); } - protected Response badRequest(T entity) { - return error(entity, HttpStatus.SC_BAD_REQUEST); + protected ResponseEntity badRequest(T entity) { + return error(entity, HttpStatus.BAD_REQUEST.value()); } - protected Response notFound(T entity) { - return error(entity, HttpStatus.SC_NOT_FOUND); + protected ResponseEntity notFound(T entity) { + return error(entity, HttpStatus.NOT_FOUND.value()); } - protected Response notFound() { - return Response.status(HttpStatus.SC_NOT_FOUND).build(); + protected ResponseEntity notFound() { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } - protected Response serverError(T entity) { - return error(entity, HttpStatus.SC_INTERNAL_SERVER_ERROR); + protected ResponseEntity serverError(T entity) { + return error(entity, HttpStatus.INTERNAL_SERVER_ERROR.value()); } - protected Response error(T entity, Integer statusCode) { - return Response + protected ResponseEntity error(T entity, Integer statusCode) { + return ResponseEntity .status(statusCode) - .entity(entity) - .build(); + .body(entity); } - protected Response badRequest() { - return Response.status(HttpStatus.SC_BAD_REQUEST).build(); + protected ResponseEntity badRequest() { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); } - protected Response ok() { - return Response.ok().build(); + protected ResponseEntity ok() { + return ResponseEntity.ok().build(); } - protected Response created() { - return Response.status(HttpStatus.SC_CREATED).build(); + protected ResponseEntity created() { + return ResponseEntity.status(HttpStatus.CREATED).build(); } - protected Response fail() { - return Response.serverError().build(); + protected ResponseEntity fail() { + return ResponseEntity.internalServerError().build(); } } diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/serializer/JacksonSerializationProvider.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/serializer/JacksonSerializationProvider.java deleted file mode 100644 index 4b2f940d0c..0000000000 --- a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/serializer/JacksonSerializationProvider.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.apache.streampipes.rest.shared.serializer; - -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; -import org.apache.streampipes.serializers.json.JacksonSerializer; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.type.TypeFactory; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.ext.Provider; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Writer; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.Arrays; - -@Provider -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public class JacksonSerializationProvider extends JsonJerseyProvider { - - private static final ObjectMapper mapper = JacksonSerializer.getObjectMapper(); - - public JacksonSerializationProvider() { - super(); - } - - - @Override - protected boolean requiredAnnotationsPresent(Annotation[] annotations) { - return Arrays.stream(annotations).anyMatch(a -> a.annotationType().equals(JacksonSerialized.class)); - } - - @Override - protected void serialize(Object t, Type type, Writer writer) throws IOException { - mapper.writeValue(writer, t); - } - - @Override - protected Object deserialize(InputStreamReader reader, Type type) throws IOException { - return mapper.readValue(reader, TypeFactory.rawClass(type)); - } -} diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/serializer/JsonJerseyProvider.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/serializer/JsonJerseyProvider.java deleted file mode 100644 index 5652b987a8..0000000000 --- a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/serializer/JsonJerseyProvider.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.streampipes.rest.shared.serializer; - -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.MultivaluedMap; -import jakarta.ws.rs.ext.MessageBodyReader; -import jakarta.ws.rs.ext.MessageBodyWriter; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; - - -public abstract class JsonJerseyProvider implements MessageBodyWriter, - MessageBodyReader { - - private final String utf8 = "UTF-8"; - - - @Override - public boolean isReadable(Class type, Type genericType, - Annotation[] annotations, MediaType mediaType) { - return jsonSerialized(mediaType) && requiredAnnotationsPresent(annotations); - } - - @Override - public Object readFrom(Class type, Type genericType, - Annotation[] annotations, MediaType mediaType, - MultivaluedMap httpHeaders, InputStream entityStream) - throws IOException, WebApplicationException { - - InputStreamReader streamReader = new InputStreamReader(entityStream, utf8); - - try { - Type jsonType; - if (type.equals(genericType)) { - jsonType = type; - } else { - jsonType = genericType; - } - - return deserialize(streamReader, jsonType); - } finally { - streamReader.close(); - } - - } - - @Override - public boolean isWriteable(Class type, Type genericType, - Annotation[] annotations, MediaType mediaType) { - return jsonSerialized(mediaType) && requiredAnnotationsPresent(annotations); - } - - @Override - public long getSize(Object t, Class type, Type genericType, - Annotation[] annotations, MediaType mediaType) { - return -1; - } - - @Override - public void writeTo(Object t, Class type, Type genericType, - Annotation[] annotations, MediaType mediaType, - MultivaluedMap httpHeaders, - OutputStream entityStream) throws IOException, - WebApplicationException { - - OutputStreamWriter writer = new OutputStreamWriter(entityStream, utf8); - - try { - Type jsonType; - if (type.equals(genericType)) { - jsonType = type; - } else { - jsonType = genericType; - } - serialize(t, jsonType, writer); - } finally { - writer.close(); - } - } - - protected boolean jsonSerialized(MediaType mediaType) { - return mediaType.getType().equals(MediaType.APPLICATION_JSON_TYPE.getType()) - && mediaType.getSubtype().equals(MediaType.APPLICATION_JSON_TYPE.getSubtype()); - } - - protected abstract boolean requiredAnnotationsPresent(Annotation[] annotations); - - protected abstract void serialize(Object t, Type type, Writer writer) throws IOException; - - protected abstract Object deserialize(InputStreamReader reader, Type type) throws IOException; -} diff --git a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/util/SpMediaType.java b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/serializer/SpringJacksonSerializer.java similarity index 65% rename from streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/util/SpMediaType.java rename to streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/serializer/SpringJacksonSerializer.java index 7b4c571e36..164309c3cb 100644 --- a/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/util/SpMediaType.java +++ b/streampipes-rest-shared/src/main/java/org/apache/streampipes/rest/shared/serializer/SpringJacksonSerializer.java @@ -15,16 +15,20 @@ * limitations under the License. * */ -package org.apache.streampipes.rest.shared.util; -import jakarta.ws.rs.core.MediaType; +package org.apache.streampipes.rest.shared.serializer; -public class SpMediaType { +import org.apache.streampipes.serializers.json.JacksonSerializer; - public static final String JSONLD = "application/ld+json"; - public static final MediaType JSONLD_TYPE = new MediaType("application", "ld+json"); +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; - public static final String APPLICATION_ZIP = "application/zip"; - public static final MediaType APPLICATION_ZIP_TYPE = new MediaType("application", "zip"); +public class SpringJacksonSerializer { + @Bean + @Primary + public ObjectMapper objectMapper() { + return JacksonSerializer.getObjectMapper(); + } } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractMonitoringResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractMonitoringResource.java index a08f982666..39cc3aff11 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractMonitoringResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractMonitoringResource.java @@ -21,13 +21,13 @@ import org.apache.streampipes.manager.monitoring.pipeline.ExtensionsServiceLogExecutor; import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.core.Response; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; public abstract class AbstractMonitoringResource extends AbstractAuthGuardedRestResource { - @GET - public Response triggerMonitoringUpdate() { + @GetMapping + public ResponseEntity triggerMonitoringUpdate() { new ExtensionsServiceLogExecutor().triggerUpdate(); return ok(); } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AccountActivationResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AccountActivationResource.java index 8d15f3fe7c..ee54e7bcc6 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AccountActivationResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AccountActivationResource.java @@ -19,28 +19,30 @@ import org.apache.streampipes.commons.exceptions.UserNotFoundException; import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource; +import org.apache.streampipes.rest.shared.exception.SpMessageException; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -@Path("/v2/activate-account") +@RestController +@RequestMapping("/api/v2/activate-account") public class AccountActivationResource extends AbstractAuthGuardedRestResource { - @GET - @Path("{recoveryCode}") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response activateUserAccount(@PathParam("recoveryCode") String recoveryCode) { + @GetMapping( + path = "{recoveryCode}", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity activateUserAccount(@PathVariable("recoveryCode") String recoveryCode) { try { getSpResourceManager().manageUsers().activateAccount(recoveryCode); return ok(); } catch (UserNotFoundException e) { - return badRequest(); + throw new SpMessageException(HttpStatus.BAD_REQUEST, e); } } } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AdapterMonitoringResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AdapterMonitoringResource.java index b7afb2aae6..b3d91cda69 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AdapterMonitoringResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AdapterMonitoringResource.java @@ -20,28 +20,29 @@ package org.apache.streampipes.rest.impl; import org.apache.streampipes.manager.monitoring.pipeline.ExtensionsLogProvider; +import org.apache.streampipes.model.monitoring.SpLogEntry; +import org.apache.streampipes.model.monitoring.SpMetricsEntry; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -@Path("/v2/adapter-monitoring") +import java.util.List; + +@RestController +@RequestMapping("/api/v2/adapter-monitoring") public class AdapterMonitoringResource extends AbstractMonitoringResource { - @Path("adapter/{elementId}/logs") - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getLogInfoForAdapter(@PathParam("elementId") String elementId) { + @GetMapping(path = "adapter/{elementId}/logs", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getLogInfoForAdapter(@PathVariable("elementId") String elementId) { return ok(ExtensionsLogProvider.INSTANCE.getLogInfosForResource(elementId)); } - @Path("adapter/{elementId}/metrics") - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getMetricsInfoForAdapter(@PathParam("elementId") String elementId) { + @GetMapping(path = "adapter/{elementId}/metrics", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getMetricsInfoForAdapter(@PathVariable("elementId") String elementId) { return ok(ExtensionsLogProvider.INSTANCE.getMetricInfosForResource(elementId)); } } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java index 5317f9d4b0..919bea60d9 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java @@ -19,109 +19,114 @@ import org.apache.streampipes.model.client.assetdashboard.AssetDashboardConfig; import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; +import org.apache.streampipes.rest.shared.exception.SpMessageException; import org.apache.streampipes.storage.api.IAssetDashboardStorage; import org.apache.streampipes.storage.management.StorageDispatcher; import org.apache.commons.io.FileUtils; -import org.glassfish.jersey.media.multipart.FormDataContentDisposition; -import org.glassfish.jersey.media.multipart.FormDataParam; - -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.PUT; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.net.FileNameMap; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.List; -@Path("/v2/asset-dashboards") +@RestController +@RequestMapping("/api/v2/asset-dashboards") public class AssetDashboardResource extends AbstractRestResource { + private static final Logger LOG = LoggerFactory.getLogger(AssetDashboardResource.class); + private static final String APP_ID = "org.apache.streampipes.apps.assetdashboard"; - @GET - @Produces(MediaType.APPLICATION_JSON) - @Path("/{dashboardId}") - public Response getAssetDashboard(@PathParam("dashboardId") String dashboardId) { + @GetMapping(path = "/{dashboardId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getAssetDashboard(@PathVariable("dashboardId") String dashboardId) { return ok(getNoSqlStorage().getAssetDashboardStorage().getAssetDashboard(dashboardId)); } - @PUT - @Produces(MediaType.APPLICATION_JSON) - @Path("/{dashboardId}") - public Response updateAssetDashboard(@PathParam("dashboardId") String dashboardId, - AssetDashboardConfig dashboardConfig) { + @PutMapping( + path = "/{dashboardId}", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity updateAssetDashboard(@PathVariable("dashboardId") String dashboardId, + @RequestBody AssetDashboardConfig dashboardConfig) { AssetDashboardConfig dashboard = getAssetDashboardStorage().getAssetDashboard(dashboardId); dashboardConfig.setRev(dashboard.getRev()); getNoSqlStorage().getAssetDashboardStorage().updateAssetDashboard(dashboardConfig); return ok(); } - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getAllDashboards() { + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getAllDashboards() { return ok(getNoSqlStorage().getAssetDashboardStorage().getAllAssetDashboards()); } - @POST - @Produces(MediaType.APPLICATION_JSON) - public Response storeAssetDashboard(AssetDashboardConfig dashboardConfig) { + @PostMapping( + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity storeAssetDashboard(@RequestBody AssetDashboardConfig dashboardConfig) { getNoSqlStorage().getAssetDashboardStorage().storeAssetDashboard(dashboardConfig); return ok(); } - @DELETE - @Produces(MediaType.APPLICATION_JSON) - @Path("/{dashboardId}") - public Response deleteAssetDashboard(@PathParam("dashboardId") String dashboardId) { + @DeleteMapping(path = "/{dashboardId}") + public ResponseEntity deleteAssetDashboard(@PathVariable("dashboardId") String dashboardId) { getNoSqlStorage().getAssetDashboardStorage().deleteAssetDashboard(dashboardId); return ok(); } - @GET - @Path("/images/{imageName}") - public Response getDashboardImage(@PathParam("imageName") String imageName) { + @GetMapping(path = "/images/{imageName}") + public ResponseEntity getDashboardImage(@PathVariable("imageName") String imageName) { try { java.nio.file.Path path = Paths.get(getTargetFile(imageName)); File file = new File(path.toString()); FileNameMap fileNameMap = URLConnection.getFileNameMap(); String mimeType = fileNameMap.getContentTypeFor(file.getName()); - return Response.ok(Files.readAllBytes(path)).type(mimeType).build(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.parseMediaType(mimeType)); + headers.setContentDispositionFormData("attachment", "filename"); // You can adjust the filename as needed + + return new ResponseEntity<>(Files.readAllBytes(path), headers, org.springframework.http.HttpStatus.OK); } catch (IOException e) { - e.printStackTrace(); - return fail(); + LOG.error(e.getMessage(), e); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } - @POST - @Produces(MediaType.APPLICATION_JSON) - @Path("/images") - public Response storeDashboardImage(@FormDataParam("file_upload") InputStream uploadedInputStream, - @FormDataParam("file_upload") FormDataContentDisposition fileDetail) { + @PostMapping(path = "/images", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity storeDashboardImage(@RequestPart("file_upload") MultipartFile fileDetail) { File targetDirectory = new File(getTargetDirectory()); if (!targetDirectory.exists()) { targetDirectory.mkdirs(); } - File targetFile = new File(getTargetFile(fileDetail.getFileName())); + File targetFile = new File(getTargetFile(fileDetail.getName())); try { - FileUtils.copyInputStreamToFile(uploadedInputStream, targetFile); + FileUtils.copyInputStreamToFile(fileDetail.getInputStream(), targetFile); return ok(); } catch (IOException e) { - e.printStackTrace(); - return fail(); + LOG.error(e.getMessage(), e); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetManagementResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetManagementResource.java index 7185e33b26..f15531ec27 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetManagementResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetManagementResource.java @@ -20,50 +20,49 @@ import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource; import org.apache.streampipes.rest.security.AuthConstants; +import org.apache.streampipes.rest.shared.exception.SpMessageException; import org.apache.streampipes.storage.api.IGenericStorage; import org.apache.streampipes.storage.management.StorageDispatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Component; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.PUT; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.List; import java.util.Map; - -@Path("/v2/assets") -@Component +@RestController +@RequestMapping("/api/v2/assets") public class AssetManagementResource extends AbstractAuthGuardedRestResource { private static final Logger LOG = LoggerFactory.getLogger(AssetManagementResource.class); private static final String APP_DOC_TYPE = "asset-management"; - @GET - @Produces(MediaType.APPLICATION_JSON) + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize(AuthConstants.HAS_READ_ASSETS_PRIVILEGE) public List> getAll() throws IOException { return getGenericStorage().findAll(APP_DOC_TYPE); } - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) + @PostMapping( + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE + ) @PreAuthorize(AuthConstants.HAS_WRITE_ASSETS_PRIVILEGE) - public Response create(String asset) { + public ResponseEntity create(@RequestBody String asset) { try { Map obj = getGenericStorage().create(asset); return ok(obj); @@ -73,46 +72,44 @@ public Response create(String asset) { } } - @GET - @Path("/{id}") - @Produces(MediaType.APPLICATION_JSON) + @GetMapping(path = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize(AuthConstants.HAS_READ_ASSETS_PRIVILEGE) - public Response getCategory(@PathParam("id") String assetId) { + public ResponseEntity> getCategory(@PathVariable("id") String assetId) { try { Map obj = getGenericStorage().findOne(assetId); return ok(obj); } catch (IOException e) { LOG.error("Could not connect to storage", e); - return fail(); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } - @PUT - @Path("/{id}") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) + @PutMapping( + path = "/{id}", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize(AuthConstants.HAS_WRITE_ASSETS_PRIVILEGE) - public Response update(@PathParam("id") String assetId, String asset) { + public ResponseEntity> update(@PathVariable("id") String assetId, + @RequestBody String asset) { try { Map obj = getGenericStorage().update(assetId, asset); return ok(obj); } catch (IOException e) { LOG.error("Could not connect to storage", e); - return fail(); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } - @DELETE - @Path("/{id}/{rev}") - @Produces(MediaType.APPLICATION_JSON) + @DeleteMapping(path = "/{id}/{rev}", produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize(AuthConstants.HAS_WRITE_ASSETS_PRIVILEGE) - public Response delete(@PathParam("id") String assetId, @PathParam("rev") String rev) { + public ResponseEntity delete(@PathVariable("id") String assetId, + @PathVariable("rev") String rev) { try { getGenericStorage().delete(assetId, rev); return ok(); } catch (IOException e) { LOG.error("Could not connect to storage", e); - return fail(); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } @@ -120,5 +117,4 @@ private IGenericStorage getGenericStorage() { return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage(); } - } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java index ad0dfc6f1f..eac307bd82 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java @@ -31,41 +31,39 @@ import org.apache.streampipes.model.message.Notifications; import org.apache.streampipes.model.message.SuccessMessage; import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; +import org.apache.streampipes.rest.shared.exception.SpMessageException; import org.apache.streampipes.user.management.jwt.JwtTokenProvider; import org.apache.streampipes.user.management.model.PrincipalUserDetails; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; -@Path("/v2/auth") +@RestController +@RequestMapping("/api/v2/auth") public class Authentication extends AbstractRestResource { @Autowired AuthenticationManager authenticationManager; - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized - @POST - @Path("/login") - public Response doLogin(LoginRequest token) { + @PostMapping( + path = "/login", + produces = org.springframework.http.MediaType.APPLICATION_JSON_VALUE, + consumes = org.springframework.http.MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doLogin(@RequestBody LoginRequest token) { try { org.springframework.security.core.Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(token.getUsername(), token.getPassword())); @@ -76,12 +74,10 @@ public Response doLogin(LoginRequest token) { } } - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @JacksonSerialized - @GET - @Path("/token/renew") - public Response doLogin() { + @GetMapping( + path = "/token/renew", + produces = org.springframework.http.MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doLogin() { try { org.springframework.security.core.Authentication auth = SecurityContextHolder.getContext().getAuthentication(); return processAuth(auth); @@ -90,44 +86,44 @@ public Response doLogin() { } } - @Path("/register") - @POST - @JacksonSerialized - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public Response doRegister(RegistrationData data) { + @PostMapping( + path = "/register", + produces = org.springframework.http.MediaType.APPLICATION_JSON_VALUE, + consumes = org.springframework.http.MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity doRegister(@RequestBody RegistrationData data) { GeneralConfig config = getSpCoreConfigurationStorage().get().getGeneralConfig(); if (!config.isAllowSelfRegistration()) { - throw new WebApplicationException(Response.Status.FORBIDDEN); + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); } data.setRoles(config.getDefaultUserRoles()); try { getSpResourceManager().manageUsers().registerUser(data); return ok(new SuccessMessage(NotificationType.REGISTRATION_SUCCESS.uiNotification())); } catch (UsernameAlreadyTakenException e) { - return badRequest(Notifications.error("This email address already exists. Please choose another address.")); + throw new SpMessageException( + HttpStatus.BAD_REQUEST, + Notifications.error("This email address already exists. Please choose another address.")); } } - @Path("restore/{username}") - @POST - @Produces(MediaType.APPLICATION_JSON) - public Response sendPasswordRecoveryLink(@PathParam("username") String username) { + @PostMapping( + path = "restore/{username}", + produces = org.springframework.http.MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity sendPasswordRecoveryLink(@PathVariable("username") String username) { try { getSpResourceManager().manageUsers().sendPasswordRecoveryLink(username); return ok(new SuccessMessage(NotificationType.PASSWORD_RECOVERY_LINK_SENT.uiNotification())); } catch (UserNotFoundException e) { return ok(); } catch (Exception e) { - return badRequest(); + throw new SpMessageException(HttpStatus.BAD_REQUEST, e); } } - @Path("settings") - @GET - @JacksonSerialized - @Produces(MediaType.APPLICATION_JSON) - public Response getAuthSettings() { + @GetMapping( + path = "settings", + produces = org.springframework.http.MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getAuthSettings() { GeneralConfig config = getSpCoreConfigurationStorage().get().getGeneralConfig(); Map response = new HashMap<>(); response.put("allowSelfRegistration", config.isAllowSelfRegistration()); @@ -136,7 +132,7 @@ public Response getAuthSettings() { return ok(response); } - private Response processAuth(org.springframework.security.core.Authentication auth) { + private ResponseEntity processAuth(org.springframework.security.core.Authentication auth) { Principal principal = ((PrincipalUserDetails) auth.getPrincipal()).getDetails(); if (principal instanceof UserAccount) { JwtAuthenticationResponse tokenResp = makeJwtResponse(auth); @@ -150,6 +146,4 @@ private JwtAuthenticationResponse makeJwtResponse(org.springframework.security.c String jwt = new JwtTokenProvider().createToken(auth); return JwtAuthenticationResponse.from(jwt); } - - } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AutoComplete.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AutoComplete.java index 755593a4b5..b201d10611 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AutoComplete.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AutoComplete.java @@ -21,20 +21,21 @@ import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; import org.apache.streampipes.vocabulary.SemanticTypeRegistry; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; -@Path("/v2/autocomplete") +import java.util.List; + +@RestController +@RequestMapping("/api/v2/autocomplete") public class AutoComplete extends AbstractRestResource { - @GET - @Path("semantic-type") - @Produces(MediaType.APPLICATION_JSON) - public Response getSemanticTypes(@QueryParam("text") String text) { + @GetMapping(path = "/semantic-type", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getSemanticTypes(@RequestParam("text") String text) { return ok(SemanticTypeRegistry.INSTANCE.matches(text)); } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/CategoryResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/CategoryResource.java index ff1b8cd8b1..90976aefa6 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/CategoryResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/CategoryResource.java @@ -21,31 +21,30 @@ import org.apache.streampipes.model.labeling.Category; import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; import org.apache.streampipes.storage.management.StorageDispatcher; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.PUT; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; +import java.util.List; import java.util.Map; -@Path("/v2/labeling/category") +@RestController +@RequestMapping("/api/v2/labeling/category") public class CategoryResource extends AbstractRestResource { - @GET - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response getAll() { + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getAll() { return ok(StorageDispatcher.INSTANCE .getNoSqlStore() .getCategoryStorageAPI() @@ -53,11 +52,11 @@ public Response getAll() { ); } - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response add(Category category) { + @PostMapping( + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE + ) + public ResponseEntity add(@RequestBody Category category) { String categoryId = StorageDispatcher.INSTANCE .getNoSqlStore() .getCategoryStorageAPI() @@ -68,23 +67,20 @@ public Response add(Category category) { .getCategoryStorageAPI().getCategory(categoryId)); } - @GET - @Path("/{categoryId}") - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response getCategory(@PathParam("categoryId") String categoryId) { + @GetMapping(path = "/{categoryId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getCategory(@PathVariable("categoryId") String categoryId) { return ok(StorageDispatcher.INSTANCE .getNoSqlStore() .getCategoryStorageAPI() .getCategory(categoryId)); } - @PUT - @Path("/{categoryId}") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response update(@PathParam("categoryId") String categoryId, Category category) { + @PutMapping( + path = "/{categoryId}", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity update(@PathVariable("categoryId") String categoryId, + @RequestBody Category category) { if (!categoryId.equals(category.getId())) { String resString = "CategoryId not the same as in message body"; Map errorDetails = new HashMap<>(); @@ -101,11 +97,8 @@ public Response update(@PathParam("categoryId") String categoryId, Category cate .getCategoryStorageAPI().getCategory(categoryId)); } - @DELETE - @Path("/{categoryId}") - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response delete(@PathParam("categoryId") String key) { + @DeleteMapping(path = "/{categoryId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity delete(@PathVariable("categoryId") String key) { StorageDispatcher.INSTANCE .getNoSqlStore() .getCategoryStorageAPI() diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/ContainerProvidedOptions.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/ContainerProvidedOptions.java index 7885ffcb97..cce62bc080 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/ContainerProvidedOptions.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/ContainerProvidedOptions.java @@ -19,24 +19,25 @@ import org.apache.streampipes.manager.operations.Operations; import org.apache.streampipes.model.runtime.RuntimeOptionsRequest; +import org.apache.streampipes.model.runtime.RuntimeOptionsResponse; import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -@Path("/v2/pe/options") +@RestController +@RequestMapping("/api/v2/pe/options") public class ContainerProvidedOptions extends AbstractRestResource { - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response fetchRemoteOptions(RuntimeOptionsRequest request) { + @PostMapping( + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE + ) + public ResponseEntity fetchRemoteOptions(@RequestBody RuntimeOptionsRequest request) { return ok(Operations.fetchRemoteOptions(request)); } } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/DataStream.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/DataStream.java index 2a65bb327b..db72f9085f 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/DataStream.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/DataStream.java @@ -20,22 +20,20 @@ import org.apache.streampipes.manager.operations.Operations; import org.apache.streampipes.model.SpDataStream; import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -@Path("/v2/streams") +@RestController +@RequestMapping("/api/v2/streams") public class DataStream extends AbstractRestResource { - @Path("/update") - @POST - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response getStreamsBySource(SpDataStream stream) { + @PostMapping(path = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getStreamsBySource(@RequestBody SpDataStream stream) { return ok(Operations.updateActualTopic(stream)); } } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/EmailResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/EmailResource.java index 31a187362e..5d592c6182 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/EmailResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/EmailResource.java @@ -21,19 +21,19 @@ import org.apache.streampipes.model.mail.SpEmail; import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; - -@Path("v2/mail") +@RestController +@RequestMapping("/api/v2/mail") public class EmailResource extends AbstractAuthGuardedRestResource { - @POST - @Consumes(MediaType.APPLICATION_JSON) - public Response sendEmail(SpEmail email) { + @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity sendEmail(@RequestBody SpEmail email) { if (getSpCoreConfigurationStorage().get().getEmailConfig().isEmailConfigured()) { try { new MailSender().sendEmail(email); diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/FunctionsResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/FunctionsResource.java index 335e72c654..0e140a4689 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/FunctionsResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/FunctionsResource.java @@ -22,63 +22,60 @@ import org.apache.streampipes.manager.monitoring.pipeline.ExtensionsLogProvider; import org.apache.streampipes.model.function.FunctionDefinition; import org.apache.streampipes.model.message.Notifications; +import org.apache.streampipes.model.message.SuccessMessage; +import org.apache.streampipes.model.monitoring.SpLogEntry; +import org.apache.streampipes.model.monitoring.SpMetricsEntry; import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import java.util.Collection; import java.util.List; -@Path("/v2/functions") +@RestController +@RequestMapping("/api/v2/functions") public class FunctionsResource extends AbstractAuthGuardedRestResource { - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getActiveFunctions() { + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getActiveFunctions() { return ok(FunctionRegistrationService.INSTANCE.getAllFunctions()); } - @GET - @Path("{functionId}") - @Produces(MediaType.APPLICATION_JSON) - public Response getFunction(@PathParam("functionId") String functionId) { + @GetMapping(path = "{functionId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getFunction(@PathVariable("functionId") String functionId) { return ok(FunctionRegistrationService.INSTANCE.getFunction(functionId)); } - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response registerFunctions(List functions) { + @PostMapping( + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE + ) + public ResponseEntity registerFunctions(@RequestBody List functions) { functions.forEach(FunctionRegistrationService.INSTANCE::registerFunction); return ok(Notifications.success("Function successfully registered")); } - @DELETE - @Path("{functionId}") - @Produces(MediaType.APPLICATION_JSON) - public Response deregisterFunction(@PathParam("functionId") String functionId) { + @DeleteMapping(path = "{functionId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity deregisterFunction(@PathVariable("functionId") String functionId) { FunctionRegistrationService.INSTANCE.deregisterFunction(functionId); return ok(Notifications.success("Function successfully deregistered")); } - @GET - @Path("{functionId}/metrics") - @Produces(MediaType.APPLICATION_JSON) - public Response getFunctionMetrics(@PathParam("functionId") String functionId) { + @GetMapping(path = "{functionId}/metrics", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getFunctionMetrics(@PathVariable("functionId") String functionId) { return ok(ExtensionsLogProvider.INSTANCE.getMetricInfosForResource(functionId)); } - @GET - @Path("{functionId}/logs") - @Produces(MediaType.APPLICATION_JSON) - public Response getFunctionLogs(@PathParam("functionId") String functionId) { + @GetMapping(path = "{functionId}/logs") + public ResponseEntity> getFunctionLogs(@PathVariable("functionId") String functionId) { return ok(ExtensionsLogProvider.INSTANCE.getLogInfosForResource(functionId)); } } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java index b9df14f9da..6efef1df9a 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/GenericStorageResource.java @@ -20,112 +20,106 @@ import org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource; import org.apache.streampipes.rest.security.AuthConstants; +import org.apache.streampipes.rest.shared.exception.SpMessageException; import org.apache.streampipes.storage.api.IGenericStorage; import org.apache.streampipes.storage.management.StorageDispatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Component; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.PUT; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.List; import java.util.Map; -@Path("/v2/storage-generic") -@Component +@RestController +@RequestMapping("/api/v2/storage-generic") public class GenericStorageResource extends AbstractAuthGuardedRestResource { public static final String APP_DOC_NAME = "appDocName"; private static final Logger LOG = LoggerFactory.getLogger(GenericStorageResource.class); - @GET - @Path("{appDocName}") - @Produces(MediaType.APPLICATION_JSON) + @GetMapping(path = "/{appDocName}", produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize(AuthConstants.HAS_READ_GENERIC_STORAGE_PRIVILEGE) - public Response getAll(@PathParam(APP_DOC_NAME) String appDocName) { + public ResponseEntity>> getAll(@PathVariable(APP_DOC_NAME) String appDocName) { try { List> assets = getGenericStorage().findAll(appDocName); return ok(assets); } catch (IOException e) { LOG.error("Could not connect to storage", e); - return fail(); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } - @POST - @Path("{appDocName}") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) + @PostMapping( + path = "/{appDocName}", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize(AuthConstants.HAS_WRITE_GENERIC_STORAGE_PRIVILEGE) - public Response create(@PathParam(APP_DOC_NAME) String appDocName, - String document) { + public ResponseEntity> create(@PathVariable(APP_DOC_NAME) String appDocName, + @RequestBody String document) { try { Map obj = getGenericStorage().create(document); return ok(obj); } catch (IOException e) { LOG.error("Could not connect to storage", e); - return fail(); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } - @GET - @Path("{appDocName}/{id}") - @Produces(MediaType.APPLICATION_JSON) + @GetMapping(path = "/{appDocName}/{id}", produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize(AuthConstants.HAS_READ_GENERIC_STORAGE_PRIVILEGE) - public Response getCategory(@PathParam(APP_DOC_NAME) String appDocName, - @PathParam("id") String documentId) { + public ResponseEntity> getCategory(@PathVariable(APP_DOC_NAME) String appDocName, + @PathVariable("id") String documentId) { try { Map obj = getGenericStorage().findOne(documentId); return ok(obj); } catch (IOException e) { LOG.error("Could not connect to storage", e); - return fail(); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } - @PUT - @Path("{appDocName}/{id}") - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) + @PutMapping( + path = "/{appDocName}/{id}", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize(AuthConstants.HAS_WRITE_GENERIC_STORAGE_PRIVILEGE) - public Response update(@PathParam(APP_DOC_NAME) String appDocName, - @PathParam("id") String documentId, - String document) { + public ResponseEntity> update(@PathVariable(APP_DOC_NAME) String appDocName, + @PathVariable("id") String documentId, + @RequestBody String document) { try { Map obj = getGenericStorage().update(documentId, document); return ok(obj); } catch (IOException e) { LOG.error("Could not connect to storage", e); - return fail(); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } - @DELETE - @Path("{appDocName}/{id}/{rev}") - @Produces(MediaType.APPLICATION_JSON) + @DeleteMapping(path = "/{appDocName}/{id}/{rev}", produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize(AuthConstants.HAS_WRITE_GENERIC_STORAGE_PRIVILEGE) - public Response delete(@PathParam(APP_DOC_NAME) String appDocName, - @PathParam("id") String documentId, - @PathParam("rev") String rev) { + public ResponseEntity delete(@PathVariable(APP_DOC_NAME) String appDocName, + @PathVariable("id") String documentId, + @PathVariable("rev") String rev) { try { getGenericStorage().delete(documentId, rev); return ok(); } catch (IOException e) { LOG.error("Could not connect to storage", e); - return fail(); + throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e); } } diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/LabelResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/LabelResource.java index 4c531434e4..69debb80c8 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/LabelResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/LabelResource.java @@ -21,41 +21,40 @@ import org.apache.streampipes.model.labeling.Category; import org.apache.streampipes.model.labeling.Label; import org.apache.streampipes.rest.core.base.impl.AbstractRestResource; -import org.apache.streampipes.rest.shared.annotation.JacksonSerialized; import org.apache.streampipes.storage.management.StorageDispatcher; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.PUT; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; +import java.util.List; import java.util.Map; -@Path("/v2/labeling/label") +@RestController +@RequestMapping("/api/v2/labeling/label") public class LabelResource extends AbstractRestResource { - @GET - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response getAllLabels() { + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getAllLabels() { return ok(StorageDispatcher.INSTANCE .getNoSqlStore() .getLabelStorageAPI() .getAllLabels()); } - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response addLabel(Label label) { + @PostMapping( + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE + ) + public ResponseEntity addLabel(@RequestBody Label label) { Category categoryForLabel = StorageDispatcher.INSTANCE .getNoSqlStore() .getCategoryStorageAPI() @@ -77,23 +76,19 @@ public Response addLabel(Label label) { .getLabel(labelId)); } - @GET - @Path("/{labelId}") - @Produces(MediaType.APPLICATION_JSON) - @JacksonSerialized - public Response getLabel(@PathParam("labelId") String labelId) { + @GetMapping(path = "/{labelId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity