Optimize API responses (#2880)

* remove generic 405 - put only where needed
* remove 429 from get/post update where not expected (not quota related in general)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2026-01-22 13:28:04 +02:00
committed by GitHub
parent 9aedbc6813
commit 5d562abd3c
12 changed files with 178 additions and 95 deletions

View File

@@ -131,9 +131,6 @@ public enum SpServerError {
SP_REPO_TENANT_NOT_EXISTS( SP_REPO_TENANT_NOT_EXISTS(
"hawkbit.server.error.repo.tenantNotExists", "hawkbit.server.error.repo.tenantNotExists",
"The entity cannot be inserted due the tenant does not exists"), "The entity cannot be inserted due the tenant does not exists"),
SP_ENTITY_LOCKED(
"hawkbit.server.error.entityLocked",
"The given entity is locked by the server."),
SP_REPO_ENTITY_READ_ONLY( SP_REPO_ENTITY_READ_ONLY(
"hawkbit.server.error.entityReadOnly", "hawkbit.server.error.entityReadOnly",
"The given entity is read only and the change cannot be completed."), "The given entity is read only and the change cannot be completed."),
@@ -149,9 +146,6 @@ public enum SpServerError {
SP_ROLLOUT_VERIFICATION_FAILED( SP_ROLLOUT_VERIFICATION_FAILED(
"hawkbit.server.error.rollout.verificationFailed", "hawkbit.server.error.rollout.verificationFailed",
"The rollout configuration could not be verified successfully"), "The rollout configuration could not be verified successfully"),
SP_REPO_OPERATION_NOT_SUPPORTED(
"hawkbit.server.error.operation.notSupported",
"Operation or method is (no longer) supported by service."),
SP_MAINTENANCE_SCHEDULE_INVALID( SP_MAINTENANCE_SCHEDULE_INVALID(
"hawkbit.server.error.maintenanceScheduleInvalid", "hawkbit.server.error.maintenanceScheduleInvalid",
"Information for schedule, duration or timezone is missing; or there is no valid maintenance window available in future."), "Information for schedule, duration or timezone is missing; or there is no valid maintenance window available in future."),

View File

@@ -13,6 +13,9 @@ import static org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants.BASE_V1_REQUEST_
import static org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants.DEPLOYMENT_BASE; import static org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants.DEPLOYMENT_BASE;
import static org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants.FEEDBACK; import static org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants.FEEDBACK;
import static org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants.MEDIA_TYPE_APPLICATION_CBOR; import static org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants.MEDIA_TYPE_APPLICATION_CBOR;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GONE_410;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.INTERNAL_SERVER_ERROR_500;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.METHOD_NOT_ALLOWED_405;
import static org.springframework.hateoas.MediaTypes.HAL_JSON_VALUE; import static org.springframework.hateoas.MediaTypes.HAL_JSON_VALUE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@@ -117,6 +120,10 @@ public interface DdiRootControllerRestApi {
@Operation(summary = "Artifact download", description = "Handles GET DdiArtifact download request. This could be " + @Operation(summary = "Artifact download", description = "Handles GET DdiArtifact download request. This could be " +
"full or partial (as specified by RFC7233 (Range Requests)) download request.") "full or partial (as specified by RFC7233 (Range Requests)) download request.")
@GetResponses @GetResponses
@ApiResponses(value = {
@ApiResponse(responseCode = INTERNAL_SERVER_ERROR_500, description = "Artifact download or decryption failed",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@GetMapping(value = BASE_V1_REQUEST_MAPPING + @GetMapping(value = BASE_V1_REQUEST_MAPPING +
"/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{fileName}") "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{fileName}")
ResponseEntity<InputStream> downloadArtifact( ResponseEntity<InputStream> downloadArtifact(
@@ -198,7 +205,7 @@ public interface DdiRootControllerRestApi {
""") """)
@PostUpdateResponses @PostUpdateResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "410", description = "Action is not active anymore.", @ApiResponse(responseCode = GONE_410, description = "Action is not active anymore.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DEPLOYMENT_BASE + @PostMapping(value = BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DEPLOYMENT_BASE +
@@ -262,6 +269,9 @@ public interface DdiRootControllerRestApi {
until the controller on the device reports a finished (either successful or error) or rejects the action, until the controller on the device reports a finished (either successful or error) or rejects the action,
e.g. the canceled actions have been started already.""") e.g. the canceled actions have been started already.""")
@PostUpdateResponses @PostUpdateResponses
@ApiResponses(value = {
@ApiResponse(responseCode = METHOD_NOT_ALLOWED_405, description = "Software module is locked", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@PostMapping(value = BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.CANCEL_ACTION + "/{actionId}/" + @PostMapping(value = BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.CANCEL_ACTION + "/{actionId}/" +
FEEDBACK, consumes = { APPLICATION_JSON_VALUE, MEDIA_TYPE_APPLICATION_CBOR }) FEEDBACK, consumes = { APPLICATION_JSON_VALUE, MEDIA_TYPE_APPLICATION_CBOR })
ResponseEntity<Void> postCancelActionFeedback( ResponseEntity<Void> postCancelActionFeedback(
@@ -375,7 +385,7 @@ public interface DdiRootControllerRestApi {
""") """)
@PostUpdateResponses @PostUpdateResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "410", description = "Action is not active anymore.", @ApiResponse(responseCode = GONE_410, description = "Action is not active anymore.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.CONFIRMATION_BASE + "/{actionId}/" + @PostMapping(value = BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.CONFIRMATION_BASE + "/{actionId}/" +
@@ -442,7 +452,7 @@ public interface DdiRootControllerRestApi {
""") """)
@PutResponses @PutResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "410", description = "Action is not active anymore.", @ApiResponse(responseCode = GONE_410, description = "Action is not active anymore.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PutMapping(value = BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.INSTALLED_BASE, @PutMapping(value = BASE_V1_REQUEST_MAPPING + "/{controllerId}/" + DdiRestConstants.INSTALLED_BASE,

View File

@@ -13,6 +13,9 @@ import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.DISTRIBUTION_S
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.LOCKED_423;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.METHOD_NOT_ALLOWED_405;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.NOT_FOUND_404;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutNoContentResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutNoContentResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses;
@@ -323,7 +326,7 @@ public interface MgmtDistributionSetRestApi {
description = "Create a list of meta data entries Required permissions: READ_REPOSITORY and UPDATE_TARGET") description = "Create a list of meta data entries Required permissions: READ_REPOSITORY and UPDATE_TARGET")
@PostCreateResponses @PostCreateResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Distribution Set not found.", @ApiResponse(responseCode = NOT_FOUND_404, description = "Distribution Set not found.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata", @PostMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/metadata",
@@ -404,6 +407,9 @@ public interface MgmtDistributionSetRestApi {
always be a list of software module IDs. Required permissions: READ_REPOSITORY and UPDATE_REPOSITORY always be a list of software module IDs. Required permissions: READ_REPOSITORY and UPDATE_REPOSITORY
""") """)
@PostUpdateNoContentResponses @PostUpdateNoContentResponses
@ApiResponses(value = {
@ApiResponse(responseCode = LOCKED_423, description = "Software module is locked", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@PostMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/assignedSM", @PostMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/assignedSM",
consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE }, consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE },
produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
@@ -421,6 +427,9 @@ public interface MgmtDistributionSetRestApi {
@Operation(summary = "Delete the assignment of the software module from the distribution set", @Operation(summary = "Delete the assignment of the software module from the distribution set",
description = "Delete an assignment. Required permission: UPDATE_REPOSITORY") description = "Delete an assignment. Required permission: UPDATE_REPOSITORY")
@DeleteResponses @DeleteResponses
@ApiResponses(value = {
@ApiResponse(responseCode = LOCKED_423, description = "Distribution set is locked", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@DeleteMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/assignedSM/{softwareModuleId}") @DeleteMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/assignedSM/{softwareModuleId}")
ResponseEntity<Void> deleteAssignSoftwareModules( ResponseEntity<Void> deleteAssignSoftwareModules(
@PathVariable("distributionSetId") Long distributionSetId, @PathVariable("distributionSetId") Long distributionSetId,
@@ -534,6 +543,10 @@ public interface MgmtDistributionSetRestApi {
cancel all actions connected to this distribution set. Required permission: UPDATE_REPOSITORY, UPDATE_TARGET cancel all actions connected to this distribution set. Required permission: UPDATE_REPOSITORY, UPDATE_TARGET
""") """)
@PostUpdateNoContentResponses @PostUpdateNoContentResponses
@ApiResponses(value = {
@ApiResponse(responseCode = METHOD_NOT_ALLOWED_405, description = "Software module is locked", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = LOCKED_423, description = "Distribution set is locked", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@PostMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/invalidate", @PostMapping(value = MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/{distributionSetId}/invalidate",
consumes = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, consumes = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE },
produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })

View File

@@ -13,6 +13,7 @@ import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.DISTRIBUTION_S
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.NOT_FOUND_404;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateNoContentResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateNoContentResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses;
@@ -271,7 +272,7 @@ public interface MgmtDistributionSetTypeRestApi {
"Required Permission: UPDATE_REPOSITORY and READ_REPOSITORY") "Required Permission: UPDATE_REPOSITORY and READ_REPOSITORY")
@PostCreateNoContentResponses @PostCreateNoContentResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Distribution Set Type not found.", @ApiResponse(responseCode = NOT_FOUND_404, description = "Distribution Set Type not found.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + "/{distributionSetTypeId}/" + @PostMapping(value = MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + "/{distributionSetTypeId}/" +
@@ -294,7 +295,7 @@ public interface MgmtDistributionSetTypeRestApi {
"Required Permission: UPDATE_REPOSITORY and READ_REPOSITORY") "Required Permission: UPDATE_REPOSITORY and READ_REPOSITORY")
@PostCreateNoContentResponses @PostCreateNoContentResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Distribution Set Type not found.", @ApiResponse(responseCode = NOT_FOUND_404, description = "Distribution Set Type not found.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + "/{distributionSetTypeId}/" + @PostMapping(value = MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING + "/{distributionSetTypeId}/" +

View File

@@ -11,11 +11,16 @@ package org.eclipse.hawkbit.mgmt.rest.api;
import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.DOWNLOAD_ARTIFACT_ORDER; import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.DOWNLOAD_ARTIFACT_ORDER;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.INTERNAL_SERVER_ERROR_500;
import java.io.InputStream; import java.io.InputStream;
import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
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 io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.eclipse.hawkbit.rest.OpenApi; import org.eclipse.hawkbit.rest.OpenApi;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -41,6 +46,10 @@ public interface MgmtDownloadArtifactRestApi {
* @return responseEntity with status ok if successful * @return responseEntity with status ok if successful
*/ */
@GetResponses @GetResponses
@ApiResponses(value = {
@ApiResponse(responseCode = INTERNAL_SERVER_ERROR_500, description = "Artifact download or decryption failed",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@GetMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts/{artifactId}/download") @GetMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts/{artifactId}/download")
@ResponseBody @ResponseBody
ResponseEntity<InputStream> downloadArtifact( ResponseEntity<InputStream> downloadArtifact(

View File

@@ -13,6 +13,7 @@ import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.ROLLOUT_ORDER;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.NOT_FOUND_404;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateNoContentResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateNoContentResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses;
@@ -372,7 +373,7 @@ public interface MgmtRolloutRestApi {
"Required Permission: CREATE_ROLLOUT") "Required Permission: CREATE_ROLLOUT")
@PostCreateResponses @PostCreateResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Rollout not found.", @ApiResponse(responseCode = NOT_FOUND_404, description = "Rollout not found.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/retry", @PostMapping(value = MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/retry",

View File

@@ -11,8 +11,12 @@ package org.eclipse.hawkbit.mgmt.rest.api;
import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.SOFTWARE_MODULE_ORDER; import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.SOFTWARE_MODULE_ORDER;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GONE_410;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.INTERNAL_SERVER_ERROR_500;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.LOCKED_423;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.NOT_FOUND_404;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses;
@@ -73,7 +77,13 @@ public interface MgmtSoftwareModuleRestApi {
@Operation(summary = "Upload artifact", description = "Handles POST request for artifact upload. Required Permission: CREATE_REPOSITORY") @Operation(summary = "Upload artifact", description = "Handles POST request for artifact upload. Required Permission: CREATE_REPOSITORY")
@PostCreateResponses @PostCreateResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Software Module not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) @ApiResponse(responseCode = NOT_FOUND_404, description = "Software Module not found",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = GONE_410, description = "Artifact binary no longer exists",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = LOCKED_423, description = "Software module is locked",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = INTERNAL_SERVER_ERROR_500, description = "Upload / store to storage or encryption failed", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts", @PostMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
@@ -96,6 +106,9 @@ public interface MgmtSoftwareModuleRestApi {
description = "Handles the GET request of retrieving all metadata of artifacts assigned to a " + description = "Handles the GET request of retrieving all metadata of artifacts assigned to a " +
"software module. Required Permission: READ_REPOSITORY") "software module. Required Permission: READ_REPOSITORY")
@GetResponses @GetResponses
@ApiResponses(value = {
@ApiResponse(responseCode = GONE_410, description = "Artifact binary no longer exists", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@GetMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts", @GetMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts",
produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
ResponseEntity<List<MgmtArtifact>> getArtifacts( ResponseEntity<List<MgmtArtifact>> getArtifacts(
@@ -112,6 +125,9 @@ public interface MgmtSoftwareModuleRestApi {
*/ */
@Operation(summary = "Return single Artifact metadata", description = "Handles the GET request of retrieving a single Artifact metadata request. Required Permission: READ_REPOSITORY") @Operation(summary = "Return single Artifact metadata", description = "Handles the GET request of retrieving a single Artifact metadata request. Required Permission: READ_REPOSITORY")
@GetResponses @GetResponses
@ApiResponses(value = {
@ApiResponse(responseCode = GONE_410, description = "Artifact binary no longer exists", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@GetMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts/{artifactId}", @GetMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts/{artifactId}",
produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
@ResponseBody @ResponseBody
@@ -129,6 +145,12 @@ public interface MgmtSoftwareModuleRestApi {
*/ */
@Operation(summary = "Delete artifact by Id", description = "Handles the DELETE request for a single Artifact assigned to a SoftwareModule. Required Permission: DELETE_REPOSITORY") @Operation(summary = "Delete artifact by Id", description = "Handles the DELETE request for a single Artifact assigned to a SoftwareModule. Required Permission: DELETE_REPOSITORY")
@DeleteResponses @DeleteResponses
@ApiResponses(value = {
@ApiResponse(responseCode = LOCKED_423, description = "Software module is locked",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = INTERNAL_SERVER_ERROR_500, description = "Artifact delete failed with internal server error",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@DeleteMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts/{artifactId}") @DeleteMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/artifacts/{artifactId}")
@ResponseBody @ResponseBody
ResponseEntity<Void> deleteArtifact( ResponseEntity<Void> deleteArtifact(
@@ -195,6 +217,10 @@ public interface MgmtSoftwareModuleRestApi {
*/ */
@Operation(summary = "Create Software Module(s)", description = "Handles the POST request of creating new software modules. The request body must always be a list of modules. Required Permission: CREATE_REPOSITORY") @Operation(summary = "Create Software Module(s)", description = "Handles the POST request of creating new software modules. The request body must always be a list of modules. Required Permission: CREATE_REPOSITORY")
@PostCreateResponses @PostCreateResponses
@ApiResponses(value = {
@ApiResponse(responseCode = INTERNAL_SERVER_ERROR_500, description = "Artifact encryption failed",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@PostMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING, @PostMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING,
consumes = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, consumes = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE },
produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }) produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
@@ -237,7 +263,8 @@ public interface MgmtSoftwareModuleRestApi {
@Operation(summary = "Creates a list of metadata for a specific Software Module", description = "Create a list of metadata entries Required Permission: UPDATE_REPOSITORY") @Operation(summary = "Creates a list of metadata for a specific Software Module", description = "Create a list of metadata entries Required Permission: UPDATE_REPOSITORY")
@PostCreateResponses @PostCreateResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Software Module not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) @ApiResponse(responseCode = NOT_FOUND_404, description = "Software Module not found",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata", @PostMapping(value = MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING + "/{softwareModuleId}/metadata",
consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE }) consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE })

View File

@@ -13,6 +13,7 @@ import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.SOFTWARE_MODUL
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.NOT_FOUND_404;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses;
@@ -148,7 +149,7 @@ public interface MgmtSoftwareModuleTypeRestApi {
"always be a list of module types. Required Permission: CREATE_REPOSITORY") "always be a list of module types. Required Permission: CREATE_REPOSITORY")
@PostCreateResponses @PostCreateResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Software Module not found", @ApiResponse(responseCode = NOT_FOUND_404, description = "Software Module not found",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING, @PostMapping(value = MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING,

View File

@@ -11,8 +11,11 @@ package org.eclipse.hawkbit.mgmt.rest.api;
import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.TARGET_ORDER; import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.TARGET_ORDER;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GONE_410;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.METHOD_NOT_ALLOWED_405;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.NOT_FOUND_404;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutNoContentResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutNoContentResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses;
@@ -288,6 +291,9 @@ public interface MgmtTargetRestApi {
*/ */
@Operation(summary = "Cancel action for a specific target", description = "Cancels an active action, only active actions can be deleted. Required Permission: UPDATE_TARGET") @Operation(summary = "Cancel action for a specific target", description = "Cancels an active action, only active actions can be deleted. Required Permission: UPDATE_TARGET")
@DeleteResponses @DeleteResponses
@ApiResponses(value = {
@ApiResponse(responseCode = METHOD_NOT_ALLOWED_405, description = "Software module is locked", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
})
@DeleteMapping(value = MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}") @DeleteMapping(value = MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}")
ResponseEntity<Void> cancelAction( ResponseEntity<Void> cancelAction(
@PathVariable("targetId") String targetId, @PathVariable("targetId") String targetId,
@@ -323,7 +329,7 @@ public interface MgmtTargetRestApi {
""") """)
@PutNoContentResponses @PutNoContentResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "410", description = "Action is not active anymore.", @ApiResponse(responseCode = GONE_410, description = "Action is not active anymore.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
}) })
@PutMapping(value = MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}/confirmation", @PutMapping(value = MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}/confirmation",
@@ -426,7 +432,7 @@ public interface MgmtTargetRestApi {
@Operation(summary = "Create a list of metadata for a specific target", description = "Create a list of metadata entries Required permissions: READ_REPOSITORY and UPDATE_TARGET") @Operation(summary = "Create a list of metadata for a specific target", description = "Create a list of metadata entries Required permissions: READ_REPOSITORY and UPDATE_TARGET")
@PostCreateResponses @PostCreateResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Target not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) @ApiResponse(responseCode = NOT_FOUND_404, description = "Target not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/metadata", @PostMapping(value = MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/metadata",
consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE }) consumes = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE })

View File

@@ -13,6 +13,7 @@ import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.TARGET_TYPE_OR
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.DeleteResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetIfExistResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.GetResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.NOT_FOUND_404;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PostCreateResponses;
import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses; import static org.eclipse.hawkbit.rest.ApiResponsesConstants.PutResponses;
@@ -146,7 +147,7 @@ public interface MgmtTargetTypeRestApi {
"types. The request body must always be a list of types. Required Permission: CREATE_TARGET") "types. The request body must always be a list of types. Required Permission: CREATE_TARGET")
@PostCreateResponses @PostCreateResponses
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "404", description = "Target type not found.", @ApiResponse(responseCode = NOT_FOUND_404, description = "Target type not found.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) content = @Content(mediaType = "application/json", schema = @Schema(hidden = true)))
}) })
@PostMapping(value = MgmtRestConstants.TARGETTYPE_V1_REQUEST_MAPPING, @PostMapping(value = MgmtRestConstants.TARGETTYPE_V1_REQUEST_MAPPING,

View File

@@ -35,18 +35,21 @@ import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
public final class ApiResponsesConstants { public final class ApiResponsesConstants {
// Response Codes // Response Codes
private static final String OK_200 = "200"; public static final String OK_200 = "200";
private static final String CREATED_201 = "201"; public static final String CREATED_201 = "201";
private static final String NO_CONTENT_204 = "204"; public static final String NO_CONTENT_204 = "204";
private static final String BAD_REQUEST_400 = "400"; public static final String BAD_REQUEST_400 = "400";
private static final String UNAUTHORIZED_401 = "401"; public static final String UNAUTHORIZED_401 = "401";
private static final String FORBIDDEN_403 = "403"; public static final String FORBIDDEN_403 = "403";
private static final String NOT_FOUND_404 = "404"; public static final String NOT_FOUND_404 = "404";
private static final String METHOD_NOT_ALLOWED_405 = "405"; public static final String METHOD_NOT_ALLOWED_405 = "405";
private static final String NOT_ACCEPTABLE_406 = "406"; public static final String NOT_ACCEPTABLE_406 = "406";
private static final String CONFLICT_409 = "409"; public static final String CONFLICT_409 = "409";
private static final String UNSUPPORTED_MEDIA_TYPE_415 = "415"; public static final String GONE_410 = "410";
private static final String TOO_MANY_REQUESTS_429 = "429"; public static final String UNSUPPORTED_MEDIA_TYPE_415 = "415";
public static final String LOCKED_423 = "423";
public static final String TOO_MANY_REQUESTS_429 = "429";
public static final String INTERNAL_SERVER_ERROR_500 = "500";
// Success Descriptions // Success Descriptions
private static final String DESC_SUCCESS_CREATED = "Successfully created"; private static final String DESC_SUCCESS_CREATED = "Successfully created";
@@ -80,6 +83,10 @@ public final class ApiResponsesConstants {
@ApiResponse( @ApiResponse(
responseCode = UNSUPPORTED_MEDIA_TYPE_415, responseCode = UNSUPPORTED_MEDIA_TYPE_415,
description = DESC_UNSUPPORTED_MEDIA_TYPE, description = DESC_UNSUPPORTED_MEDIA_TYPE,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = TOO_MANY_REQUESTS_429,
description = DESC_TOO_MANY_REQUESTS,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))) content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true)))
}) })
@CommonErrorResponses @CommonErrorResponses
@@ -114,6 +121,10 @@ public final class ApiResponsesConstants {
description = DESC_CONFLICT, description = DESC_CONFLICT,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))), content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))),
@ApiResponse(responseCode = UNSUPPORTED_MEDIA_TYPE_415, description = DESC_UNSUPPORTED_MEDIA_TYPE, @ApiResponse(responseCode = UNSUPPORTED_MEDIA_TYPE_415, description = DESC_UNSUPPORTED_MEDIA_TYPE,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = TOO_MANY_REQUESTS_429,
description = DESC_TOO_MANY_REQUESTS,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))) content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true)))
}) })
@CommonErrorResponses @CommonErrorResponses
@@ -169,6 +180,10 @@ public final class ApiResponsesConstants {
@ApiResponse( @ApiResponse(
responseCode = UNSUPPORTED_MEDIA_TYPE_415, responseCode = UNSUPPORTED_MEDIA_TYPE_415,
description = DESC_UNSUPPORTED_MEDIA_TYPE, description = DESC_UNSUPPORTED_MEDIA_TYPE,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = TOO_MANY_REQUESTS_429,
description = DESC_TOO_MANY_REQUESTS,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))) content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true)))
}) })
@CommonErrorResponses @CommonErrorResponses
@@ -189,6 +204,10 @@ public final class ApiResponsesConstants {
@ApiResponse( @ApiResponse(
responseCode = UNSUPPORTED_MEDIA_TYPE_415, responseCode = UNSUPPORTED_MEDIA_TYPE_415,
description = DESC_UNSUPPORTED_MEDIA_TYPE, description = DESC_UNSUPPORTED_MEDIA_TYPE,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = TOO_MANY_REQUESTS_429,
description = DESC_TOO_MANY_REQUESTS,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))) content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true)))
}) })
@CommonErrorResponses @CommonErrorResponses
@@ -220,15 +239,8 @@ public final class ApiResponsesConstants {
responseCode = FORBIDDEN_403, responseCode = FORBIDDEN_403,
description = DESC_FORBIDDEN, description = DESC_FORBIDDEN,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))), content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = METHOD_NOT_ALLOWED_405, description = DESC_METHOD_NOT_ALLOWED,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))),
@ApiResponse( @ApiResponse(
responseCode = NOT_ACCEPTABLE_406, description = DESC_NOT_ACCEPTABLE, responseCode = NOT_ACCEPTABLE_406, description = DESC_NOT_ACCEPTABLE,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))),
@ApiResponse(
responseCode = TOO_MANY_REQUESTS_429,
description = DESC_TOO_MANY_REQUESTS,
content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true))) content = @Content(mediaType = MEDIA_TYPE_JSON, schema = @Schema(hidden = true)))
}) })
private @interface CommonErrorResponses { private @interface CommonErrorResponses {

View File

@@ -9,6 +9,16 @@
*/ */
package org.eclipse.hawkbit.rest; package org.eclipse.hawkbit.rest;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CONFLICT;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.GONE;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.LOCKED;
import static org.springframework.http.HttpStatus.METHOD_NOT_ALLOWED;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.TOO_MANY_REQUESTS;
import java.io.IOException; import java.io.IOException;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
@@ -93,62 +103,60 @@ public class RestConfiguration {
public static class ResponseExceptionHandler { public static class ResponseExceptionHandler {
private static final Map<SpServerError, HttpStatus> ERROR_TO_HTTP_STATUS = new EnumMap<>(SpServerError.class); private static final Map<SpServerError, HttpStatus> ERROR_TO_HTTP_STATUS = new EnumMap<>(SpServerError.class);
private static final HttpStatus DEFAULT_RESPONSE_STATUS = HttpStatus.INTERNAL_SERVER_ERROR; private static final HttpStatus DEFAULT_RESPONSE_STATUS = INTERNAL_SERVER_ERROR;
private static final String MESSAGE_FORMATTER_SEPARATOR = " "; private static final String MESSAGE_FORMATTER_SEPARATOR = " ";
private static final String LOG_EXCEPTION_FORMAT = "Handling exception {} of request {}"; private static final String LOG_EXCEPTION_FORMAT = "Handling exception {} of request {}";
static { static {
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_ENTITY_NOT_EXISTS, HttpStatus.NOT_FOUND); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_ENTITY_NOT_EXISTS, NOT_FOUND);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_ENTITY_ALREADY_EXISTS, HttpStatus.CONFLICT); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_ENTITY_ALREADY_EXISTS, CONFLICT);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_ENTITY_READ_ONLY, HttpStatus.FORBIDDEN); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_ENTITY_READ_ONLY, FORBIDDEN);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_SORT_PARAM_INVALID_DIRECTION, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_SORT_PARAM_INVALID_DIRECTION, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_SORT_PARAM_INVALID_FIELD, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_SORT_PARAM_INVALID_FIELD, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_SORT_PARAM_SYNTAX, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_SORT_PARAM_SYNTAX, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_RSQL_PARAM_INVALID_FIELD, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_RSQL_PARAM_INVALID_FIELD, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_RSQL_SEARCH_PARAM_SYNTAX, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REST_RSQL_SEARCH_PARAM_SYNTAX, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_INSUFFICIENT_PERMISSION, HttpStatus.FORBIDDEN); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_INSUFFICIENT_PERMISSION, FORBIDDEN);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED, INTERNAL_SERVER_ERROR);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_ENCRYPTION_NOT_SUPPORTED, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_ENCRYPTION_NOT_SUPPORTED, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_ENCRYPTION_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_ENCRYPTION_FAILED, INTERNAL_SERVER_ERROR);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_SHA256_MATCH, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_DELETE_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_DELETE_FAILED, INTERNAL_SERVER_ERROR);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_BINARY_DELETED, HttpStatus.GONE); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_BINARY_DELETED, GONE);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_LOAD_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ARTIFACT_LOAD_FAILED, INTERNAL_SERVER_ERROR);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_QUOTA_EXCEEDED, HttpStatus.TOO_MANY_REQUESTS); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_QUOTA_EXCEEDED, TOO_MANY_REQUESTS);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_FILE_SIZE_QUOTA_EXCEEDED, HttpStatus.TOO_MANY_REQUESTS); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_FILE_SIZE_QUOTA_EXCEEDED, TOO_MANY_REQUESTS);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_STORAGE_QUOTA_EXCEEDED, HttpStatus.TOO_MANY_REQUESTS); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_STORAGE_QUOTA_EXCEEDED, TOO_MANY_REQUESTS);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ACTION_NOT_CANCELABLE, HttpStatus.METHOD_NOT_ALLOWED); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ACTION_NOT_CANCELABLE, METHOD_NOT_ALLOWED);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ACTION_NOT_FORCE_QUITABLE, HttpStatus.METHOD_NOT_ALLOWED); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ACTION_NOT_FORCE_QUITABLE, METHOD_NOT_ALLOWED);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_CREATION_FAILED_MISSING_MODULE, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_CREATION_FAILED_MISSING_MODULE, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_MODULE_UNSUPPORTED, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_MODULE_UNSUPPORTED, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_TYPE_UNDEFINED, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_TYPE_UNDEFINED, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_TENANT_NOT_EXISTS, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_TENANT_NOT_EXISTS, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ENTITY_LOCKED, HttpStatus.LOCKED); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ROLLOUT_ILLEGAL_STATE, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ROLLOUT_ILLEGAL_STATE, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_VALUE_INVALID, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_VALUE_INVALID, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_KEY_INVALID, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_KEY_INVALID, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_INVALID_TARGET_ADDRESS, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_INVALID_TARGET_ADDRESS, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_CONSTRAINT_VIOLATION, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_CONSTRAINT_VIOLATION, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_CONCURRENT_MODIFICATION, CONFLICT);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_OPERATION_NOT_SUPPORTED, HttpStatus.GONE); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_MAINTENANCE_SCHEDULE_INVALID, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_CONCURRENT_MODIFICATION, HttpStatus.CONFLICT); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_TARGET_ATTRIBUTES_INVALID, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_MAINTENANCE_SCHEDULE_INVALID, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_AUTO_CONFIRMATION_ALREADY_ACTIVE, CONFLICT);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_TARGET_ATTRIBUTES_INVALID, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_AUTO_ASSIGN_ACTION_TYPE_INVALID, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_AUTO_CONFIRMATION_ALREADY_ACTIVE, HttpStatus.CONFLICT); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_VALUE_CHANGE_NOT_ALLOWED, FORBIDDEN);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_AUTO_ASSIGN_ACTION_TYPE_INVALID, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_MULTIASSIGNMENT_NOT_ENABLED, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_VALUE_CHANGE_NOT_ALLOWED, HttpStatus.FORBIDDEN); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_NO_WEIGHT_PROVIDED_IN_MULTIASSIGNMENT_MODE, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_MULTIASSIGNMENT_NOT_ENABLED, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_TARGET_TYPE_IN_USE, CONFLICT);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_NO_WEIGHT_PROVIDED_IN_MULTIASSIGNMENT_MODE, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_TARGET_TYPE_INCOMPATIBLE, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_TARGET_TYPE_IN_USE, HttpStatus.CONFLICT); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_TARGET_TYPE_KEY_OR_NAME_REQUIRED, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_TARGET_TYPE_INCOMPATIBLE, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_INVALID, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_TARGET_TYPE_KEY_OR_NAME_REQUIRED, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_INCOMPLETE, BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_INVALID, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_LOCKED, LOCKED);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DS_INCOMPLETE, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DELETED, NOT_FOUND);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_LOCKED, HttpStatus.LOCKED); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_STOP_ROLLOUT_FAILED, LOCKED);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_DELETED, HttpStatus.NOT_FOUND);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_STOP_ROLLOUT_FAILED, HttpStatus.LOCKED);
} }
/** /**
@@ -186,7 +194,7 @@ public class RestConfiguration {
logRequest(request, ex); logRequest(request, ex);
log.warn("File streaming failed: {}", ex.getMessage()); log.warn("File streaming failed: {}", ex.getMessage());
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); return new ResponseEntity<>(INTERNAL_SERVER_ERROR);
} }
/** /**
@@ -206,7 +214,7 @@ public class RestConfiguration {
logRequest(request, ex); logRequest(request, ex);
final ExceptionInfo response = createExceptionInfo(new MessageNotReadableException()); final ExceptionInfo response = createExceptionInfo(new MessageNotReadableException());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(response, BAD_REQUEST);
} }
/** /**
@@ -229,7 +237,7 @@ public class RestConfiguration {
response.setExceptionClass(ex.getClass().getName()); response.setExceptionClass(ex.getClass().getName());
response.setErrorCode(SpServerError.SP_REPO_CONSTRAINT_VIOLATION.getKey()); response.setErrorCode(SpServerError.SP_REPO_CONSTRAINT_VIOLATION.getKey());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(response, BAD_REQUEST);
} }
/** /**
@@ -249,7 +257,7 @@ public class RestConfiguration {
response.setExceptionClass(ex.getClass().getName()); response.setExceptionClass(ex.getClass().getName());
response.setErrorCode(SpServerError.SP_REPO_CONSTRAINT_VIOLATION.getKey()); response.setErrorCode(SpServerError.SP_REPO_CONSTRAINT_VIOLATION.getKey());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(response, BAD_REQUEST);
} }
/** /**
@@ -271,7 +279,7 @@ public class RestConfiguration {
log.warn("Request {} lead to MultipartException without root cause message:\n{}", request.getRequestURL(), ex.getStackTrace()); log.warn("Request {} lead to MultipartException without root cause message:\n{}", request.getRequestURL(), ex.getStackTrace());
} }
return new ResponseEntity<>(createExceptionInfo(new MultiPartFileUploadException(responseCause)), HttpStatus.BAD_REQUEST); return new ResponseEntity<>(createExceptionInfo(new MultiPartFileUploadException(responseCause)), BAD_REQUEST);
} }
@ExceptionHandler({ DataIntegrityViolationException.class }) @ExceptionHandler({ DataIntegrityViolationException.class })
@@ -287,7 +295,7 @@ public class RestConfiguration {
response.setMessage("The data provided violates integrity rules. Please ensure all required fields are valid."); response.setMessage("The data provided violates integrity rules. Please ensure all required fields are valid.");
response.setExceptionClass(ex.getClass().getName()); response.setExceptionClass(ex.getClass().getName());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(response, BAD_REQUEST);
} }
private static HttpStatus getStatusOrDefault(final SpServerError error) { private static HttpStatus getStatusOrDefault(final SpServerError error) {