Enrichment cordinator service, added job validation
Added validation of EI job data agains the registerred json schema.
Improved tests.
Improved documentation.
Change-Id: I86fe031b22aa0378d82181a019e8f0743f283e8a
Issue-ID: NONRTRIC-173
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
diff --git a/enrichment-coordinator-service/docs/api.yaml b/enrichment-coordinator-service/docs/api.yaml
index bb34e2b..2fbf934 100644
--- a/enrichment-coordinator-service/docs/api.yaml
+++ b/enrichment-coordinator-service/docs/api.yaml
@@ -17,8 +17,7 @@
get:
tags:
- A1-E Enrichment Data Consumer API
- summary: Query EI type identifiers
- description: DETAILS TBD
+ summary: EI type identifiers
operationId: getEiTypeIdentifiersUsingGET
produces:
- application/json
@@ -40,8 +39,7 @@
get:
tags:
- A1-E Enrichment Data Consumer API
- summary: Definitions for an individual EI Type
- description: Query EI type
+ summary: Individual EI type
operationId: getEiTypeUsingGET
produces:
- application/json
@@ -69,8 +67,7 @@
get:
tags:
- A1-E Enrichment Data Consumer API
- summary: Query EI job identifiers
- description: Returns the identifiers for an EI Type
+ summary: EI job identifiers
operationId: getEiJobIdsUsingGET
produces:
- application/json
@@ -88,7 +85,7 @@
type: string
responses:
'200':
- description: EI type
+ description: EI job identifiers
schema:
type: array
items:
@@ -139,7 +136,6 @@
tags:
- A1-E Enrichment Data Consumer API
summary: Individual EI Job
- description: Create or update an EI Job
operationId: putIndividualEiJobUsingPUT
consumes:
- application/json
@@ -184,7 +180,6 @@
tags:
- A1-E Enrichment Data Consumer API
summary: Individual EI Job
- description: Delete an EI job
operationId: deleteIndividualEiJobUsingDELETE
produces:
- application/json
@@ -254,8 +249,7 @@
get:
tags:
- Enrichment Data Producer API
- summary: Query EI producer identifiers
- description: DETAILS TBD
+ summary: EI producer identifiers
operationId: getEiProducerIdentifiersUsingGET
produces:
- application/json
@@ -277,8 +271,7 @@
get:
tags:
- Enrichment Data Producer API
- summary: Job definition for an individual EI producer
- description: Query EI jobs
+ summary: Individual EI producer
operationId: getEiProducerUsingGET
produces:
- application/json
@@ -292,7 +285,7 @@
'200':
description: EI Jobs
schema:
- $ref: '#/definitions/producer_ei_type_info'
+ $ref: '#/definitions/producer_registration_info'
'401':
description: Unauthorized
'403':
@@ -305,8 +298,7 @@
put:
tags:
- Enrichment Data Producer API
- summary: Definitions for an individual EI producer
- description: Put EI producer
+ summary: Individual EI producer
operationId: putEiProducerUsingPUT
consumes:
- application/json
@@ -343,8 +335,7 @@
delete:
tags:
- Enrichment Data Producer API
- summary: Individual EI Producer
- description: Delete an EI Producer
+ summary: Individual EI producer
operationId: deleteEiProducerUsingDELETE
produces:
- application/json
@@ -376,8 +367,8 @@
get:
tags:
- Enrichment Data Producer API
- summary: Job definition for an individual EI producer
- description: Query EI producer jobs
+ summary: EI job definitions
+ description: EI job definitions for one EI producer
operationId: getEiProducerJobsUsingGET
produces:
- application/json
@@ -407,8 +398,7 @@
get:
tags:
- Enrichment Data Producer API
- summary: Query EI type identifiers
- description: DETAILS TBD
+ summary: EI type identifiers
operationId: getEiTypeIdentifiersUsingGET_1
produces:
- application/json
@@ -430,8 +420,7 @@
get:
tags:
- Enrichment Data Producer API
- summary: Definitions for an individual EI Type
- description: Query EI type
+ summary: Individual EI Type
operationId: getEiTypeUsingGET_1
produces:
- application/json
@@ -459,7 +448,7 @@
post:
tags:
- Producer Simulator
- summary: Callback for job creation
+ summary: Callback for EI job creation
operationId: jobCreatedCallbackUsingPOST
consumes:
- application/json
@@ -490,7 +479,7 @@
post:
tags:
- Producer Simulator
- summary: Callback for job deletion
+ summary: Callback for EI job deletion
operationId: jobDeletedCallbackUsingPOST
consumes:
- application/json
@@ -522,12 +511,12 @@
type: object
required:
- job_data
- - owner
+ - job_owner
properties:
job_data:
type: object
description: EI Type specific job data
- owner:
+ job_owner:
type: string
description: Identity of the owner of the job
title: ei_job_info
@@ -540,8 +529,8 @@
operational_state:
type: string
description: |-
- Operational state, values:
- ENABLED: TBD
+ Operational state, values:
+ ENABLED: TBD
DISABLED: TBD.
enum:
- ENABLED
@@ -562,37 +551,37 @@
detail:
type: string
example: EI job type not found
- description: ' A human-readable explanation specific to this occurrence of the problem.'
+ description: A human-readable explanation specific to this occurrence of the problem.
status:
type: integer
format: int32
- example: 503
- description: 'The HTTP status code generated by the origin server for this occurrence of the problem. '
+ example: 404
+ description: The HTTP status code generated by the origin server for this occurrence of the problem.
title: error_information
description: 'Problem as defined in https://tools.ietf.org/html/rfc7807'
producer_ei_job_request:
type: object
required:
- - identity
+ - ei_job_identity
properties:
- identity:
- type: string
- description: Json for the job data
- job_data:
+ ei_job_data:
type: object
description: Json for the job data
- type_identity:
+ ei_job_identity:
+ type: string
+ description: Idenitity of the EI job
+ ei_type_identity:
type: string
description: Type idenitity for the job
title: producer_ei_job_request
- description: Information EI job start
+ description: The body of the EI producer callbacks for EI job creation and deletion
producer_ei_type_info:
type: object
properties:
- job_data_schema:
+ ei_job_data_schema:
type: object
description: Json schema for the job data
- producer_ids:
+ ei_producer_ids:
type: array
description: Registered producers
items:
@@ -604,25 +593,25 @@
required:
- ei_type_identity
properties:
+ ei_job_data_schema:
+ type: object
+ description: Json schema for the job data
ei_type_identity:
type: string
description: EI type identity
- job_data_schema:
- type: object
- description: Json schema for the job data
title: producer_ei_type_registration_info
description: Information for an EI type
producer_registration_info:
type: object
required:
- - job_creation_callback_url
- - job_deletion_callback_url
+ - ei_job_creation_callback_url
+ - ei_job_deletion_callback_url
- supported_ei_types
properties:
- job_creation_callback_url:
+ ei_job_creation_callback_url:
type: string
description: callback for job creation
- job_deletion_callback_url:
+ ei_job_deletion_callback_url:
type: string
description: callback for job deletion
supported_ei_types:
@@ -631,5 +620,5 @@
items:
$ref: '#/definitions/producer_ei_type_registration_info'
title: producer_registration_info
- description: Information for an EI Producer
+ description: Information for an EI producer
diff --git a/enrichment-coordinator-service/pom.xml b/enrichment-coordinator-service/pom.xml
index 3f156a7..a069c0d 100644
--- a/enrichment-coordinator-service/pom.xml
+++ b/enrichment-coordinator-service/pom.xml
@@ -153,6 +153,12 @@
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
+ <!-- https://mvnrepository.com/artifact/com.github.erosb/everit-json-schema -->
+ <dependency>
+ <groupId>com.github.erosb</groupId>
+ <artifactId>everit-json-schema</artifactId>
+ <version>1.12.1</version>
+ </dependency>
<!-- Actuator dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/SwaggerConfig.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/SwaggerConfig.java
index ee80183..6fa38aa 100644
--- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/SwaggerConfig.java
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/SwaggerConfig.java
@@ -23,10 +23,6 @@
import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.Predicates;
-import org.oransc.enrichment.clients.ProducerJobInfo;
-import org.oransc.enrichment.controllers.consumer.ConsumerEiJobInfo;
-import org.oransc.enrichment.controllers.producer.ProducerEiTypeInfo;
-import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
@@ -67,17 +63,13 @@
public Docket api(TypeResolver resolver) {
return new Docket(DocumentationType.SWAGGER_2) //
.apiInfo(apiInfo()) //
- .additionalModels(resolver.resolve(ConsumerEiJobInfo.class)) //
- .additionalModels(resolver.resolve(ProducerRegistrationInfo.class)) //
- .additionalModels(resolver.resolve(ProducerEiTypeInfo.class)) //
- .additionalModels(resolver.resolve(ProducerJobInfo.class)) //
.select() //
.apis(RequestHandlerSelectors.any()) //
.paths(PathSelectors.any()) //
- .paths(Predicates.not(PathSelectors.regex("/error"))) //
- // this endpoint is not implemented, but was visible for Swagger
- .paths(Predicates.not(PathSelectors.regex("/actuator.*"))) //
- // this endpoint is implemented by spring framework, exclude for now
+ .paths(Predicates.not(PathSelectors.regex("/error"))) // this endpoint is not implemented, but was
+ // visible for Swagger
+ .paths(Predicates.not(PathSelectors.regex("/actuator.*"))) // this endpoint is implemented by spring
+ // framework, exclude for now
.build();
}
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/clients/ProducerJobInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/clients/ProducerJobInfo.java
index 60762b9..ff91221 100644
--- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/clients/ProducerJobInfo.java
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/clients/ProducerJobInfo.java
@@ -31,22 +31,24 @@
import org.oransc.enrichment.repository.EiType;
@Gson.TypeAdapters
-@ApiModel(value = "producer_ei_job_request", description = "Information EI job start")
+@ApiModel(
+ value = "producer_ei_job_request",
+ description = "The body of the EI producer callbacks for EI job creation and deletion")
public class ProducerJobInfo {
- @ApiModelProperty(value = "Json for the job data", required = true)
- @SerializedName("identity")
- @JsonProperty("identity")
+ @ApiModelProperty(value = "Idenitity of the EI job", required = true)
+ @SerializedName("ei_job_identity")
+ @JsonProperty("ei_job_identity")
public String id;
@ApiModelProperty(value = "Type idenitity for the job")
- @SerializedName("type_identity")
- @JsonProperty("type_identity")
+ @SerializedName("ei_type_identity")
+ @JsonProperty("ei_type_identity")
public String typeId;
@ApiModelProperty(value = "Json for the job data")
- @SerializedName("job_data")
- @JsonProperty("job_data")
+ @SerializedName("ei_job_data")
+ @JsonProperty("ei_job_data")
public Object jobData;
public ProducerJobInfo(Object jobData, String id, String typeId) {
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/ErrorResponse.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/ErrorResponse.java
index edaa3bb..c90a649 100644
--- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/ErrorResponse.java
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/ErrorResponse.java
@@ -61,7 +61,7 @@
}
@ApiModelProperty(
- example = "503",
+ example = "404",
value = "The HTTP status code generated by the origin server for this occurrence of the problem.")
public Integer getStatus() {
return status;
@@ -73,7 +73,6 @@
public String getDetail() {
return this.detail;
}
-
}
@ApiModelProperty(value = "message")
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerController.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerController.java
index c43a495..a74e487 100644
--- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerController.java
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerController.java
@@ -20,9 +20,9 @@
package org.oransc.enrichment.controllers.consumer;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import com.google.gson.JsonObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -34,9 +34,13 @@
import java.util.ArrayList;
import java.util.List;
+import org.everit.json.schema.Schema;
+import org.everit.json.schema.loader.SchemaLoader;
+import org.json.JSONObject;
import org.oransc.enrichment.clients.ProducerCallbacks;
import org.oransc.enrichment.configuration.ApplicationConfig;
import org.oransc.enrichment.controllers.ErrorResponse;
+import org.oransc.enrichment.exceptions.ServiceException;
import org.oransc.enrichment.repository.EiJob;
import org.oransc.enrichment.repository.EiJobs;
import org.oransc.enrichment.repository.EiType;
@@ -79,7 +83,7 @@
.create(); //
@GetMapping(path = ConsumerConsts.API_ROOT + "/eitypes", produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Query EI type identifiers", notes = "DETAILS TBD")
+ @ApiOperation(value = "EI type identifiers", notes = "")
@ApiResponses(
value = { //
@ApiResponse(
@@ -99,7 +103,7 @@
}
@GetMapping(path = ConsumerConsts.API_ROOT + "/eitypes/{eiTypeId}", produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Definitions for an individual EI Type", notes = "Query EI type")
+ @ApiOperation(value = "Individual EI type", notes = "")
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "EI type", response = ConsumerEiTypeInfo.class), //
@@ -121,7 +125,7 @@
@GetMapping(
path = ConsumerConsts.API_ROOT + "/eitypes/{eiTypeId}/eijobs",
produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Query EI job identifiers", notes = "Returns the EI Job identifiers for an EI Type")
+ @ApiOperation(value = "EI job identifiers", notes = "")
@ApiResponses(
value = { //
@ApiResponse(
@@ -206,7 +210,7 @@
@DeleteMapping(
path = ConsumerConsts.API_ROOT + "/eitypes/{eiTypeId}/eijobs/{eiJobId}",
produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Individual EI Job", notes = "Delete EI job")
+ @ApiOperation(value = "Individual EI Job", notes = "")
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "Not used", response = void.class),
@@ -232,7 +236,7 @@
path = ConsumerConsts.API_ROOT + "/eitypes/{eiTypeId}/eijobs/{eiJobId}", //
produces = MediaType.APPLICATION_JSON_VALUE, //
consumes = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Individual EI Job", notes = "Create or update an EI Job")
+ @ApiOperation(value = "Individual EI Job", notes = "")
@ApiResponses(
value = { //
@ApiResponse(code = 201, message = "Job created", response = void.class), //
@@ -258,11 +262,24 @@
}
}
- private void validateJobData(Object schemaObj, Object json) {
- if (schemaObj instanceof JsonObject) {
- JsonObject schema = (JsonObject) schemaObj;
- logger.debug("schema {} json {}", schema, json);
+ private void validateJobData(Object schemaObj, Object object) throws ServiceException {
+ if (schemaObj == null) {
+ return; // schema is optional for now
}
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+
+ String schemaAsString = mapper.writeValueAsString(schemaObj);
+ JSONObject schemaJSON = new JSONObject(schemaAsString);
+ Schema schema = SchemaLoader.load(schemaJSON);
+
+ String objectAsString = mapper.writeValueAsString(object);
+ JSONObject json = new JSONObject(objectAsString);
+ schema.validate(json);
+ } catch (Exception e) {
+ throw new ServiceException("Json validation failure", e);
+ }
+
}
// Status TBD
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobInfo.java
index 515c616..8255c43 100644
--- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobInfo.java
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/consumer/ConsumerEiJobInfo.java
@@ -33,8 +33,8 @@
public class ConsumerEiJobInfo {
@ApiModelProperty(value = "Identity of the owner of the job", required = true)
- @SerializedName("owner")
- @JsonProperty(value = "owner", required = true)
+ @SerializedName("job_owner")
+ @JsonProperty(value = "job_owner", required = true)
public String owner;
@ApiModelProperty(value = "EI Type specific job data", required = true)
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerController.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerController.java
index b88e047..c24e559 100644
--- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerController.java
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerController.java
@@ -81,7 +81,7 @@
ProducerCallbacks producerCallbacks;
@GetMapping(path = ProducerConsts.API_ROOT + "/eitypes", produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Query EI type identifiers", notes = "DETAILS TBD")
+ @ApiOperation(value = "EI type identifiers", notes = "")
@ApiResponses(
value = { //
@ApiResponse(
@@ -101,7 +101,7 @@
}
@GetMapping(path = ProducerConsts.API_ROOT + "/eitypes/{eiTypeId}", produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Definitions for an individual EI Type", notes = "Query EI type")
+ @ApiOperation(value = "Individual EI Type", notes = "")
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "EI type", response = ProducerEiTypeInfo.class), //
@@ -121,7 +121,7 @@
}
@GetMapping(path = ProducerConsts.API_ROOT + "/eiproducers", produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Query EI producer identifiers", notes = "DETAILS TBD")
+ @ApiOperation(value = "EI producer identifiers", notes = "")
@ApiResponses(
value = { //
@ApiResponse(
@@ -143,10 +143,10 @@
@GetMapping(
path = ProducerConsts.API_ROOT + "/eiproducers/{eiProducerId}",
produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Definition for an individual EI producer", notes = "Query EI jobs")
+ @ApiOperation(value = "Individual EI producer", notes = "")
@ApiResponses(
value = { //
- @ApiResponse(code = 200, message = "EI Jobs", response = ProducerEiTypeInfo.class), //
+ @ApiResponse(code = 200, message = "EI Jobs", response = ProducerRegistrationInfo.class), //
@ApiResponse(
code = 404,
message = "Enrichment Information producer is not found",
@@ -165,7 +165,7 @@
@GetMapping(
path = ProducerConsts.API_ROOT + "/eiproducers/{eiProducerId}/eijobs",
produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Job definitions for an individual EI producer", notes = "Query EI producer jobs")
+ @ApiOperation(value = "EI job definitions", notes = "EI job definitions for one EI producer")
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "EI jobs", response = ProducerJobInfo.class, responseContainer = "List"), //
@@ -194,7 +194,7 @@
@PutMapping(
path = ProducerConsts.API_ROOT + "/eiproducers/{eiProducerId}",
produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Individual EI producer", notes = "Put EI producer")
+ @ApiOperation(value = "Individual EI producer", notes = "")
@ApiResponses(
value = { //
@ApiResponse(code = 201, message = "Producer created", response = void.class), //
@@ -220,7 +220,7 @@
@DeleteMapping(
path = ProducerConsts.API_ROOT + "/eiproducers/{eiProducerId}",
produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Individual EI Producer", notes = "Delete an EI Producer")
+ @ApiOperation(value = "Individual EI producer", notes = "")
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "Not used", response = void.class),
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerEiTypeInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerEiTypeInfo.java
index 1c9167b..9a82161 100644
--- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerEiTypeInfo.java
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerEiTypeInfo.java
@@ -35,13 +35,13 @@
public class ProducerEiTypeInfo {
@ApiModelProperty(value = "Json schema for the job data")
- @SerializedName("job_data_schema")
- @JsonProperty("job_data_schema")
+ @SerializedName("ei_job_data_schema")
+ @JsonProperty("ei_job_data_schema")
public Object jobDataSchema;
@ApiModelProperty(value = "Registered producers")
- @SerializedName("producer_ids")
- @JsonProperty(value = "producer_ids", required = true)
+ @SerializedName("ei_producer_ids")
+ @JsonProperty(value = "ei_producer_ids", required = true)
public Collection<String> producerIds;
public ProducerEiTypeInfo(Object jobDataSchema, Collection<String> producers) {
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerRegistrationInfo.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerRegistrationInfo.java
index c48c716..1ef2ed4 100644
--- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerRegistrationInfo.java
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/controllers/producer/ProducerRegistrationInfo.java
@@ -31,7 +31,7 @@
import org.immutables.gson.Gson;
@Gson.TypeAdapters
-@ApiModel(value = "producer_registration_info", description = "Information for an EI Producer")
+@ApiModel(value = "producer_registration_info", description = "Information for an EI producer")
public class ProducerRegistrationInfo {
@Gson.TypeAdapters
@@ -44,8 +44,8 @@
public String eiTypeId;
@ApiModelProperty(value = "Json schema for the job data")
- @SerializedName("job_data_schema")
- @JsonProperty("job_data_schema")
+ @SerializedName("ei_job_data_schema")
+ @JsonProperty("ei_job_data_schema")
public Object jobDataSchema;
public ProducerEiTypeRegistrationInfo(Object jobDataSchema, String eiTypeId) {
@@ -63,13 +63,13 @@
public Collection<ProducerEiTypeRegistrationInfo> types;
@ApiModelProperty(value = "callback for job creation", required = true)
- @SerializedName("job_creation_callback_url")
- @JsonProperty(value = "job_creation_callback_url", required = true)
+ @SerializedName("ei_job_creation_callback_url")
+ @JsonProperty(value = "ei_job_creation_callback_url", required = true)
public String jobCreationCallbackUrl;
@ApiModelProperty(value = "callback for job deletion", required = true)
- @SerializedName("job_deletion_callback_url")
- @JsonProperty(value = "job_deletion_callback_url", required = true)
+ @SerializedName("ei_job_deletion_callback_url")
+ @JsonProperty(value = "ei_job_deletion_callback_url", required = true)
public String jobDeletionCallbackUrl;
public ProducerRegistrationInfo(Collection<ProducerEiTypeRegistrationInfo> types, String jobCreationCallbackUrl,
diff --git a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/MultiMap.java b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/MultiMap.java
index e64ea22..c2b8270 100644
--- a/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/MultiMap.java
+++ b/enrichment-coordinator-service/src/main/java/org/oransc/enrichment/repository/MultiMap.java
@@ -27,9 +27,9 @@
import java.util.Vector;
/**
- * Dynamic representation of all Rics in the system.
+ * A map, where each key can be bound to may values (where each value has an own
+ * ID)
*/
-
public class MultiMap<T> {
private final Map<String, Map<String, T>> map = new HashMap<>();
diff --git a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java
index cf34076..e92705e 100644
--- a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java
+++ b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/ApplicationTest.java
@@ -24,14 +24,13 @@
import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonParser;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import org.junit.jupiter.api.AfterEach;
@@ -49,14 +48,12 @@
import org.oransc.enrichment.controllers.producer.ProducerConsts;
import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo;
import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo.ProducerEiTypeRegistrationInfo;
+import org.oransc.enrichment.exceptions.ServiceException;
import org.oransc.enrichment.repository.EiJob;
import org.oransc.enrichment.repository.EiJobs;
-import org.oransc.enrichment.repository.EiProducer;
import org.oransc.enrichment.repository.EiProducers;
import org.oransc.enrichment.repository.EiType;
import org.oransc.enrichment.repository.EiTypes;
-import org.oransc.enrichment.repository.ImmutableEiJob;
-import org.oransc.enrichment.repository.ImmutableEiProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -86,6 +83,8 @@
"app.webclient.trust-store=./config/truststore.jks"})
class ApplicationTest {
private static final Logger logger = LoggerFactory.getLogger(ApplicationTest.class);
+ private final String EI_TYPE_ID = "typeId";
+ private final String EI_JOB_PROPERTY = "\"property1\"";
@Autowired
ApplicationContext context;
@@ -137,52 +136,55 @@
}
@Test
- void getEiTypes() throws Exception {
- addEiType("test");
+ void testGetEiTypes() throws Exception {
+ putEiProducerWithOneType("test");
String url = ConsumerConsts.API_ROOT + "/eitypes";
String rsp = restClient().get(url).block();
assertThat(rsp).isEqualTo("[\"test\"]");
}
@Test
- void getEiType() throws Exception {
- addEiType("test");
+ void testGetEiType() throws Exception {
+ putEiProducerWithOneType("test");
String url = ConsumerConsts.API_ROOT + "/eitypes/test";
String rsp = restClient().get(url).block();
assertThat(rsp).contains("job_data_schema");
}
@Test
- void getEiTypeNotFound() throws Exception {
+ void testGetEiTypeNotFound() throws Exception {
String url = ConsumerConsts.API_ROOT + "/eitypes/junk";
testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI type: junk");
}
@Test
- void getEiJobsIds() throws Exception {
- addEiJob("typeId", "jobId");
+ void testGetEiJobsIds() throws Exception {
+ putEiProducerWithOneType(EI_TYPE_ID);
+ putEiJob(EI_TYPE_ID, "jobId");
String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs";
String rsp = restClient().get(url).block();
assertThat(rsp).isEqualTo("[\"jobId\"]");
}
@Test
- void getEiJobTypeNotFound() throws Exception {
+ void testGetEiJobTypeNotFound() throws Exception {
String url = ConsumerConsts.API_ROOT + "/eitypes/junk/eijobs";
testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI type: junk");
}
@Test
- void getEiJob() throws Exception {
- addEiJob("typeId", "jobId");
+ void testGetEiJob() throws Exception {
+ putEiProducerWithOneType(EI_TYPE_ID);
+ putEiJob(EI_TYPE_ID, "jobId");
String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
String rsp = restClient().get(url).block();
assertThat(rsp).contains("job_data");
}
@Test
- void getEiJobStatus() throws Exception {
- addEiJob("typeId", "jobId");
+ void testGetEiJobStatus() throws Exception {
+ putEiProducerWithOneType(EI_TYPE_ID);
+ putEiJob(EI_TYPE_ID, "jobId");
String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId/status";
String rsp = restClient().get(url).block();
assertThat(rsp).contains("ENABLED");
@@ -191,8 +193,9 @@
// Status TBD
@Test
- void deleteEiJob() throws Exception {
- addEiJob("typeId", "jobId");
+ void testDeleteEiJob() throws Exception {
+ putEiProducerWithOneType(EI_TYPE_ID);
+ putEiJob(EI_TYPE_ID, "jobId");
assertThat(this.eiJobs.size()).isEqualTo(1);
String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
restClient().delete(url).block();
@@ -204,8 +207,8 @@
}
@Test
- void putEiJob() throws Exception {
- addEiType("typeId");
+ void testPutEiJob() throws Exception {
+ putEiProducerWithOneType(EI_TYPE_ID);
String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
String body = gson.toJson(eiJobInfo());
@@ -225,8 +228,21 @@
}
@Test
- void getEiProducerTypes() throws Exception {
- this.addEiJob("typeId", "jobId");
+ void testPutEiJob_jsonSchemavalidationError() throws Exception {
+ putEiProducerWithOneType(EI_TYPE_ID);
+
+ String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
+ // The element with name "property1" is mandatory in the schema
+ ConsumerEiJobInfo jobInfo = new ConsumerEiJobInfo(jsonObject("{ \"XXstring\" : \"value\" }"), "owner");
+ String body = gson.toJson(jobInfo);
+
+ testErrorCode(restClient().put(url, body), HttpStatus.NOT_FOUND, "Json validation failure");
+ }
+
+ @Test
+ void testGetEiProducerTypes() throws Exception {
+ putEiProducerWithOneType(EI_TYPE_ID);
+ putEiJob(EI_TYPE_ID, "jobId");
String url = ProducerConsts.API_ROOT + "/eitypes";
ResponseEntity<String> resp = restClient().getForEntity(url).block();
@@ -234,31 +250,53 @@
}
@Test
- void putEiProducer() throws Exception {
+ void testPutEiProducer() throws Exception {
String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
- String body = gson.toJson(producerEiRegistratioInfo());
+ String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
assertThat(this.eiTypes.size()).isEqualTo(1);
- EiType type = this.eiTypes.getType("typeId");
+ EiType type = this.eiTypes.getType(EI_TYPE_ID);
assertThat(type.getProducerIds().contains("eiProducerId")).isTrue();
assertThat(this.eiProducers.size()).isEqualTo(1);
- assertThat(this.eiProducers.get("eiProducerId").eiTypes().iterator().next().getId().equals("typeId")).isTrue();
+ assertThat(this.eiProducers.get("eiProducerId").eiTypes().iterator().next().getId().equals(EI_TYPE_ID))
+ .isTrue();
resp = restClient().putForEntity(url, body).block();
assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
+
+ resp = restClient().getForEntity(url).block();
+ assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
+ assertThat(resp.getBody()).isEqualTo(body);
}
@Test
- void putEiProducerExistingJob() throws Exception {
- this.addEiJob("typeId", "jobId");
+ void testPutEiProducerExistingJob() throws Exception {
+ putEiProducerWithOneType(EI_TYPE_ID);
+ putEiJob(EI_TYPE_ID, "jobId");
String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
- String body = gson.toJson(producerEiRegistratioInfo());
+ String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
+ restClient().putForEntity(url, body).block();
- ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
- assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
+ ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
+ await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(2));
+ ProducerJobInfo request = simulatorResults.jobsStarted.get(0);
+ assertThat(request.id).isEqualTo("jobId");
+ }
+
+ @Test
+ void testPutProducerAndEiJob() throws Exception {
+ String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
+ String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
+ restClient().putForEntity(url, body).block();
+ assertThat(this.eiTypes.size()).isEqualTo(1);
+ this.eiTypes.getType(EI_TYPE_ID);
+
+ url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
+ body = gson.toJson(eiJobInfo());
+ restClient().putForEntity(url, body).block();
ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(1));
@@ -267,13 +305,14 @@
}
@Test
- void getEiJobsForProducer() {
- this.addEiJob("typeId", "jobId1");
- this.addEiJob("typeId", "jobId2");
+ void testGetEiJobsForProducer() throws JsonMappingException, JsonProcessingException, ServiceException {
+ putEiProducerWithOneType(EI_TYPE_ID);
+ putEiJob(EI_TYPE_ID, "jobId1");
+ putEiJob(EI_TYPE_ID, "jobId2");
// PUT a consumer
String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
- String body = gson.toJson(producerEiRegistratioInfo());
+ String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
restClient().putForEntity(url, body).block();
url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId/eijobs";
@@ -281,77 +320,95 @@
assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
ProducerJobInfo[] parsedResp = gson.fromJson(resp.getBody(), ProducerJobInfo[].class);
- assertThat(parsedResp[0].typeId).isEqualTo("typeId");
- assertThat(parsedResp[1].typeId).isEqualTo("typeId");
+ assertThat(parsedResp[0].typeId).isEqualTo(EI_TYPE_ID);
+ assertThat(parsedResp[1].typeId).isEqualTo(EI_TYPE_ID);
}
@Test
- void deleteEiProducer() throws Exception {
+ void testDeleteEiProducer() throws Exception {
String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
String url2 = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId2";
- String body = gson.toJson(producerEiRegistratioInfo());
+ String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
restClient().putForEntity(url, body).block();
restClient().putForEntity(url2, body).block();
assertThat(this.eiProducers.size()).isEqualTo(2);
- EiType type = this.eiTypes.getType("typeId");
+ EiType type = this.eiTypes.getType(EI_TYPE_ID);
assertThat(type.getProducerIds().contains("eiProducerId")).isTrue();
assertThat(type.getProducerIds().contains("eiProducerId2")).isTrue();
restClient().deleteForEntity(url).block();
assertThat(this.eiProducers.size()).isEqualTo(1);
- assertThat(this.eiTypes.getType("typeId").getProducerIds().contains("eiProducerId")).isFalse();
+ assertThat(this.eiTypes.getType(EI_TYPE_ID).getProducerIds().contains("eiProducerId")).isFalse();
restClient().deleteForEntity(url2).block();
assertThat(this.eiProducers.size()).isEqualTo(0);
assertThat(this.eiTypes.size()).isEqualTo(0);
}
- ProducerEiTypeRegistrationInfo producerEiTypeRegistrationInfo() {
- return new ProducerEiTypeRegistrationInfo(jsonObject(), "typeId");
+ ProducerEiTypeRegistrationInfo producerEiTypeRegistrationInfo(String typeId)
+ throws JsonMappingException, JsonProcessingException {
+ return new ProducerEiTypeRegistrationInfo(jsonSchemaObject(), typeId);
}
- ProducerRegistrationInfo producerEiRegistratioInfo() {
+ ProducerRegistrationInfo producerEiRegistratioInfo(String typeId)
+ throws JsonMappingException, JsonProcessingException {
Collection<ProducerEiTypeRegistrationInfo> types = new ArrayList<>();
- types.add(producerEiTypeRegistrationInfo());
+ types.add(producerEiTypeRegistrationInfo(typeId));
return new ProducerRegistrationInfo(types, baseUrl() + ProducerSimulatorController.JOB_CREATED_URL,
baseUrl() + ProducerSimulatorController.JOB_DELETED_URL);
}
- ConsumerEiJobInfo eiJobInfo() {
+ ConsumerEiJobInfo eiJobInfo() throws JsonMappingException, JsonProcessingException {
return new ConsumerEiJobInfo(jsonObject(), "owner");
}
- JsonObject jsonObject() {
- JsonObject jsonObj = new JsonObject();
- JsonElement e = new JsonPrimitive(111);
- jsonObj.add("param", e);
- return jsonObj;
+ Object jsonObject(String json) {
+ try {
+ return JsonParser.parseString(json).getAsJsonObject();
+ } catch (Exception e) {
+ throw new NullPointerException(e.toString());
+ }
}
- private EiJob addEiJob(String typeId, String jobId) {
- EiType type = addEiType(typeId);
- EiJob job = ImmutableEiJob.builder() //
- .id(jobId) //
- .type(type) //
- .owner("owner") //
- .jobData(jsonObject()) //
- .build();
- this.eiJobs.put(job);
- return job;
+ Object jsonSchemaObject() {
+ // a json schema with one mandatory property named "string"
+ String schemaStr = "{" //
+ + "\"$schema\": \"http://json-schema.org/draft-04/schema#\"," //
+ + "\"type\": \"object\"," //
+ + "\"properties\": {" //
+ + EI_JOB_PROPERTY + " : {" //
+ + " \"type\": \"string\"" //
+ + " }" //
+ + "}," //
+ + "\"required\": [" //
+ + EI_JOB_PROPERTY //
+ + "]" //
+ + "}"; //
+ return jsonObject(schemaStr);
}
- private EiType addEiType(String typeId) {
- EiType eiType = new EiType(typeId, jsonObject());
- this.eiTypes.put(eiType); //
- EiProducer producer = ImmutableEiProducer.builder() //
- .id("producerId") //
- .eiTypes(Arrays.asList(eiType)) //
- .jobCreationCallbackUrl(baseUrl() + ProducerSimulatorController.JOB_CREATED_URL) //
- .jobDeletionCallbackUrl(baseUrl() + ProducerSimulatorController.JOB_DELETED_URL) //
- .build();
- this.eiProducers.put(producer);
- eiType.addProducer(producer);
- return eiType;
+ Object jsonObject() {
+ return jsonObject("{ " + EI_JOB_PROPERTY + " : \"value\" }");
+ }
+
+ private EiJob putEiJob(String eiTypeId, String jobId)
+ throws JsonMappingException, JsonProcessingException, ServiceException {
+
+ String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/" + jobId;
+ String body = gson.toJson(eiJobInfo());
+ restClient().putForEntity(url, body).block();
+
+ return this.eiJobs.getJob(jobId);
+ }
+
+ private EiType putEiProducerWithOneType(String eiTypeId)
+ throws JsonMappingException, JsonProcessingException, ServiceException {
+ String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
+ String body = gson.toJson(producerEiRegistratioInfo(eiTypeId));
+
+ restClient().putForEntity(url, body).block();
+ assertThat(this.eiTypes.size()).isEqualTo(1);
+ return this.eiTypes.getType(eiTypeId);
}
private String baseUrl() {
diff --git a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ProducerSimulatorController.java b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ProducerSimulatorController.java
index 307d409..b6b8bc3 100644
--- a/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ProducerSimulatorController.java
+++ b/enrichment-coordinator-service/src/test/java/org/oransc/enrichment/controller/ProducerSimulatorController.java
@@ -72,7 +72,7 @@
private TestResults testResults = new TestResults();
@PostMapping(path = JOB_CREATED_URL, produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Callback for job creation", notes = "")
+ @ApiOperation(value = "Callback for EI job creation", notes = "")
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "OK", response = void.class)}//
@@ -93,7 +93,7 @@
}
@PostMapping(path = JOB_DELETED_URL, produces = MediaType.APPLICATION_JSON_VALUE)
- @ApiOperation(value = "Callback for job deletion", notes = "")
+ @ApiOperation(value = "Callback for EI job deletion", notes = "")
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "OK", response = void.class)}//