NONRTRIC - Enrichment Coordinator Service, Changed error codes 05/6905/2
authorPatrikBuhr <patrik.buhr@est.tech>
Thu, 21 Oct 2021 10:40:22 +0000 (12:40 +0200)
committerPatrikBuhr <patrik.buhr@est.tech>
Thu, 21 Oct 2021 11:49:34 +0000 (13:49 +0200)
Changed HTTP error codes

Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
Issue-ID: NONRTRIC-594
Change-Id: Ic82bc3ca39df3a4d63aac57becb4f8d4713933cd

enrichment-coordinator-service/api/ecs-api.json
enrichment-coordinator-service/api/ecs-api.yaml
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/a1e/A1eController.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1consumer/ConsumerController.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/r1producer/ProducerController.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/exceptions/ServiceException.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/InfoJobs.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/InfoProducers.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/InfoTypeSubscriptions.java
enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/InfoTypes.java
enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java

index 0e8164e..7da2270 100644 (file)
                         "description": "Information type is not found",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     },
-                    "406": {
+                    "409": {
                         "description": "The Information type has one or several active producers",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
                     },
                     "400": {
-                        "description": "Bad request",
+                        "description": "Input validation failed",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                 },
                         "description": "Producer created",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
                     },
+                    "400": {
+                        "description": "Input validation failed",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
                     "404": {
-                        "description": "Producer not found",
+                        "description": "Producer type not found",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                 },
                         "description": "Job created",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
                     },
+                    "400": {
+                        "description": "Input validation failed",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
                     "404": {
                         "description": "Enrichment Information type is not found",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
+                    "409": {
+                        "description": "Cannot modify job type",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                 },
                 "parameters": [{
                         "description": "Job created",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Void"}}}
                     },
+                    "400": {
+                        "description": "Input validation failed",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
                     "404": {
                         "description": "Information type is not found",
                         "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
+                    },
+                    "409": {
+                        "description": "Cannot modify job type",
+                        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProblemDetails"}}}
                     }
                 },
                 "parameters": [
index 3445ede..c4463b0 100644 (file)
@@ -189,7 +189,7 @@ paths:
               schema:
                 $ref: '#/components/schemas/Void'
         400:
-          description: Bad request
+          description: Input validation failed
           content:
             application/json:
               schema:
@@ -226,7 +226,7 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/ProblemDetails'
-        406:
+        409:
           description: The Information type has one or several active producers
           content:
             application/json:
@@ -429,8 +429,14 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Void'
+        400:
+          description: Input validation failed
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
         404:
-          description: Producer not found
+          description: Producer type not found
           content:
             application/json:
               schema:
@@ -564,12 +570,24 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Void'
+        400:
+          description: Input validation failed
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
         404:
           description: Enrichment Information type is not found
           content:
             application/json:
               schema:
                 $ref: '#/components/schemas/ProblemDetails'
+        409:
+          description: Cannot modify job type
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
     delete:
       tags:
       - A1-EI (registration)
@@ -711,12 +729,24 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Void'
+        400:
+          description: Input validation failed
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
         404:
           description: Information type is not found
           content:
             application/json:
               schema:
                 $ref: '#/components/schemas/ProblemDetails'
+        409:
+          description: Cannot modify job type
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ProblemDetails'
     delete:
       tags:
       - Data consumer
index 5f796b8..9609e27 100644 (file)
@@ -277,8 +277,18 @@ public class A1eController {
             @ApiResponse(
                 responseCode = "404",
                 description = "Enrichment Information type is not found", //
-                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))),
+            @ApiResponse(
+                responseCode = "400",
+                description = "Input validation failed", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
+            @ApiResponse(
+                responseCode = "409",
+                description = "Cannot modify job type", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class)))
+
         })
+
     public Mono<ResponseEntity<Object>> putIndividualEiJob( //
         @PathVariable("eiJobId") String eiJobId, //
         @RequestBody A1eEiJobInfo eiJobObject) {
@@ -289,7 +299,7 @@ public class A1eController {
             .flatMap(this::startEiJob) //
             .doOnNext(newEiJob -> this.eiJobs.put(newEiJob)) //
             .flatMap(newEiJob -> Mono.just(new ResponseEntity<>(isNewJob ? HttpStatus.CREATED : HttpStatus.OK)))
-            .onErrorResume(throwable -> Mono.just(ErrorResponse.create(throwable, HttpStatus.NOT_FOUND)));
+            .onErrorResume(throwable -> Mono.just(ErrorResponse.create(throwable, HttpStatus.INTERNAL_SERVER_ERROR)));
     }
 
     private Mono<InfoJob> startEiJob(InfoJob newEiJob) {
@@ -320,7 +330,7 @@ public class A1eController {
         if (url != null && !url.isEmpty()) {
             URI uri = new URI(url);
             if (!uri.isAbsolute()) {
-                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.CONFLICT);
+                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.BAD_REQUEST);
             }
         }
     }
@@ -338,7 +348,7 @@ public class A1eController {
                 JSONObject json = new JSONObject(objectAsString);
                 schema.validate(json);
             } catch (Exception e) {
-                throw new ServiceException("Json validation failure " + e.toString(), HttpStatus.CONFLICT);
+                throw new ServiceException("Json validation failure " + e.toString(), HttpStatus.BAD_REQUEST);
             }
         }
     }
index 9de57d5..47a4a2e 100644 (file)
@@ -282,8 +282,15 @@ public class ConsumerController {
             @ApiResponse(
                 responseCode = "404",
                 description = "Information type is not found", //
-                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) //
-        })
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
+            @ApiResponse(
+                responseCode = "400",
+                description = "Input validation failed", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
+            @ApiResponse(
+                responseCode = "409",
+                description = "Cannot modify job type", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class)))})
     public Mono<ResponseEntity<Object>> putIndividualInfoJob( //
         @PathVariable("infoJobId") String jobId, //
         @Parameter(
@@ -460,7 +467,7 @@ public class ConsumerController {
         if (url != null && !url.isEmpty()) {
             URI uri = new URI(url);
             if (!uri.isAbsolute()) {
-                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.CONFLICT);
+                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.BAD_REQUEST);
             }
         }
     }
@@ -478,7 +485,7 @@ public class ConsumerController {
                 JSONObject json = new JSONObject(objectAsString);
                 schema.validate(json);
             } catch (Exception e) {
-                throw new ServiceException("Json validation failure " + e.toString(), HttpStatus.CONFLICT);
+                throw new ServiceException("Json validation failure " + e.toString(), HttpStatus.BAD_REQUEST);
             }
         }
     }
index 0aa6974..cad6a04 100644 (file)
@@ -138,7 +138,7 @@ public class ProducerController {
                 content = @Content(schema = @Schema(implementation = VoidResponse.class))), //
             @ApiResponse(
                 responseCode = "400",
-                description = "Bad request", //
+                description = "Input validation failed", //
                 content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class)))})
     @Operation(summary = "Individual Information Type", description = "")
     public ResponseEntity<Object> putInfoType( //
@@ -175,7 +175,7 @@ public class ProducerController {
                 description = "Information type is not found", //
                 content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
             @ApiResponse(
-                responseCode = "406",
+                responseCode = "409",
                 description = "The Information type has one or several active producers", //
                 content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) //
         })
@@ -188,7 +188,7 @@ public class ProducerController {
         }
         if (!this.infoProducers.getProducersForType(type).isEmpty()) {
             String firstProducerId = this.infoProducers.getProducersForType(type).iterator().next().getId();
-            return ErrorResponse.create("The type has active producers: " + firstProducerId, HttpStatus.NOT_ACCEPTABLE);
+            return ErrorResponse.create("The type has active producers: " + firstProducerId, HttpStatus.CONFLICT);
         }
         this.infoTypes.remove(type);
         infoJobs.getJobsForType(type).forEach(job -> infoJobs.remove(job, infoProducers)); // Delete jobs for the type
@@ -329,7 +329,11 @@ public class ProducerController {
                 content = @Content(schema = @Schema(implementation = VoidResponse.class))), //
             @ApiResponse(
                 responseCode = "404",
-                description = "Producer not found", //
+                description = "Producer type not found", //
+                content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))), //
+            @ApiResponse(
+                responseCode = "400",
+                description = "Input validation failed", //
                 content = @Content(schema = @Schema(implementation = ErrorResponse.ErrorInfo.class))) //
         })
     public ResponseEntity<Object> putInfoProducer( //
@@ -341,19 +345,23 @@ public class ProducerController {
             InfoProducer previousDefinition = this.infoProducers.get(infoProducerId);
             this.infoProducers.registerProducer(toProducerRegistrationInfo(infoProducerId, registrationInfo));
             return new ResponseEntity<>(previousDefinition == null ? HttpStatus.CREATED : HttpStatus.OK);
-        } catch (Exception e) {
-            return ErrorResponse.create(e, HttpStatus.NOT_FOUND);
+        } catch (ServiceException e) {
+            return ErrorResponse.create(e, e.getHttpStatus());
         }
     }
 
-    private void validateUri(String url) throws URISyntaxException, ServiceException {
+    private void validateUri(String url) throws ServiceException {
         if (url != null && !url.isEmpty()) {
-            URI uri = new URI(url);
-            if (!uri.isAbsolute()) {
-                throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.CONFLICT);
+            try {
+                URI uri = new URI(url);
+                if (!uri.isAbsolute()) {
+                    throw new ServiceException("URI: " + url + " is not absolute", HttpStatus.BAD_REQUEST);
+                }
+            } catch (URISyntaxException e) {
+                throw new ServiceException(e.getMessage(), HttpStatus.BAD_REQUEST);
             }
         } else {
-            throw new ServiceException("Missing required URL", HttpStatus.CONFLICT);
+            throw new ServiceException("Missing required URL", HttpStatus.BAD_REQUEST);
         }
     }
 
@@ -381,8 +389,8 @@ public class ProducerController {
             final InfoProducer producer = this.infoProducers.getProducer(infoProducerId);
             this.infoProducers.deregisterProducer(producer);
             return new ResponseEntity<>(HttpStatus.NO_CONTENT);
-        } catch (Exception e) {
-            return ErrorResponse.create(e, HttpStatus.NOT_FOUND);
+        } catch (ServiceException e) {
+            return ErrorResponse.create(e, e.getHttpStatus());
         }
     }
 
index ffccf80..bce786f 100644 (file)
@@ -28,11 +28,6 @@ public class ServiceException extends Exception {
     @Getter
     private final HttpStatus httpStatus;
 
-    public ServiceException(String message) {
-        super(message);
-        this.httpStatus = null;
-    }
-
     public ServiceException(String message, Exception originalException) {
         super(message, originalException);
         this.httpStatus = null;
index 52fa1d6..7469e08 100644 (file)
@@ -43,6 +43,7 @@ import org.oransc.enrichment.controllers.r1producer.ProducerCallbacks;
 import org.oransc.enrichment.exceptions.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
 import org.springframework.util.FileSystemUtils;
 
 /**
@@ -91,7 +92,7 @@ public class InfoJobs {
     public synchronized InfoJob getJob(String id) throws ServiceException {
         InfoJob ric = allEiJobs.get(id);
         if (ric == null) {
-            throw new ServiceException("Could not find Information job: " + id);
+            throw new ServiceException("Could not find Information job: " + id, HttpStatus.NOT_FOUND);
         }
         return ric;
     }
index 57e7922..1102e36 100644 (file)
@@ -36,6 +36,7 @@ import org.oransc.enrichment.exceptions.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Component;
 
 /**
@@ -110,7 +111,7 @@ public class InfoProducers {
     public synchronized InfoProducer getProducer(String id) throws ServiceException {
         InfoProducer p = allEiProducers.get(id);
         if (p == null) {
-            throw new ServiceException("Could not find Information Producer: " + id);
+            throw new ServiceException("Could not find Information Producer: " + id, HttpStatus.NOT_FOUND);
         }
         return p;
     }
index 2d6da4f..65978e1 100644 (file)
@@ -47,6 +47,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
 import org.springframework.util.FileSystemUtils;
 
 import reactor.core.publisher.Flux;
@@ -118,7 +119,7 @@ public class InfoTypeSubscriptions {
     public synchronized SubscriptionInfo getSubscription(String id) throws ServiceException {
         SubscriptionInfo p = allSubscriptions.get(id);
         if (p == null) {
-            throw new ServiceException("Could not find Information subscription: " + id);
+            throw new ServiceException("Could not find Information subscription: " + id, HttpStatus.NOT_FOUND);
         }
         return p;
     }
@@ -196,7 +197,8 @@ public class InfoTypeSubscriptions {
 
                 private Mono<String> error() {
                     return Mono.error(new ServiceException(
-                        "No notifyTypeRegistered handler found for interface version " + apiVersion));
+                        "No notifyTypeRegistered handler found for interface version " + apiVersion,
+                        HttpStatus.INTERNAL_SERVER_ERROR));
                 }
             };
         }
index 85664f6..c23875b 100644 (file)
@@ -42,6 +42,7 @@ import org.oransc.enrichment.configuration.ApplicationConfig;
 import org.oransc.enrichment.exceptions.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
 import org.springframework.util.FileSystemUtils;
 
 /**
@@ -84,7 +85,7 @@ public class InfoTypes {
     public synchronized InfoType getType(String id) throws ServiceException {
         InfoType type = allEiTypes.get(id);
         if (type == null) {
-            throw new ServiceException("Information type not found: " + id);
+            throw new ServiceException("Information type not found: " + id, HttpStatus.NOT_FOUND);
         }
         return type;
     }
index 4d64ef6..4418429 100644 (file)
@@ -490,7 +490,10 @@ class ApplicationTest {
             "targetUri", "jobStatusUrl");
         String body = gson.toJson(jobInfo);
 
-        testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Json validation failure");
+        testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "Json validation failure");
+
+        testErrorCode(restClient().put(url, "{jojo}"), HttpStatus.BAD_REQUEST, "", false);
+
     }
 
     @Test
@@ -503,7 +506,7 @@ class ApplicationTest {
             new ConsumerJobInfo("typeId", jsonObject("{ \"XXstring\" : \"value\" }"), "owner", "targetUri", null);
         String body = gson.toJson(jobInfo);
 
-        testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Json validation failure");
+        testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "Json validation failure");
     }
 
     @Test
@@ -515,7 +518,7 @@ class ApplicationTest {
         ConsumerJobInfo jobInfo = new ConsumerJobInfo(TYPE_ID, jsonObject(), "owner", "junk", null);
         String body = gson.toJson(jobInfo);
 
-        testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "URI: junk is not absolute");
+        testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "URI: junk is not absolute");
     }
 
     @Test
@@ -552,6 +555,8 @@ class ApplicationTest {
         String url = ProducerConsts.API_ROOT + "/info-types/" + TYPE_ID;
         String body = "{}";
         testErrorCode(restClient().put(url, body), HttpStatus.BAD_REQUEST, "No schema provided");
+
+        testErrorCode(restClient().post(url, body), HttpStatus.METHOD_NOT_ALLOWED, "", false);
     }
 
     @Test
@@ -572,8 +577,7 @@ class ApplicationTest {
     void producerDeleteEiTypeExistingProducer() throws Exception {
         putInfoProducerWithOneType(PRODUCER_ID, TYPE_ID);
         String url = ProducerConsts.API_ROOT + "/info-types/" + TYPE_ID;
-        testErrorCode(restClient().delete(url), HttpStatus.NOT_ACCEPTABLE,
-            "The type has active producers: " + PRODUCER_ID);
+        testErrorCode(restClient().delete(url), HttpStatus.CONFLICT, "The type has active producers: " + PRODUCER_ID);
         assertThat(this.infoTypes.size()).isEqualTo(1);
     }