diff options
author | adheli.tavares <adheli.tavares@est.tech> | 2024-07-19 11:51:37 +0100 |
---|---|---|
committer | adheli.tavares <adheli.tavares@est.tech> | 2024-07-19 11:55:19 +0100 |
commit | b8c49fd30e2e660198d29e599a0ccecf184b2071 (patch) | |
tree | 3a45c42aabee26b5b4abcca5e5922896ce4bcf79 | |
parent | 9551484946f5c53f9a0ea37c3b0a7810b5d77fab (diff) |
Uplift of json schema validator library
Issue-ID: POLICY-5084
Change-Id: Ie24719570c43a9f7b0fdac28973cc50d8eb7ed2c
Signed-off-by: adheli.tavares <adheli.tavares@est.tech>
11 files changed, 77 insertions, 48 deletions
diff --git a/context/context-management/src/main/java/org/onap/policy/apex/context/impl/schema/SchemaHelperFactory.java b/context/context-management/src/main/java/org/onap/policy/apex/context/impl/schema/SchemaHelperFactory.java index 08289e642..3602ce12a 100644 --- a/context/context-management/src/main/java/org/onap/policy/apex/context/impl/schema/SchemaHelperFactory.java +++ b/context/context-management/src/main/java/org/onap/policy/apex/context/impl/schema/SchemaHelperFactory.java @@ -1,7 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * Modifications Copyright (C) 2019-2020 Nordix Foundation. + * Modifications Copyright (C) 2019-2020, 2024 Nordix Foundation. * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -84,7 +84,7 @@ public class SchemaHelperFactory { } // Get the class for the schema helper using reflection - Object schemaHelperObject = null; + Object schemaHelperObject; final String pluginClass = schemaHelperParameters.getSchemaHelperPluginClass(); try { schemaHelperObject = Class.forName(pluginClass).getDeclaredConstructor().newInstance(); @@ -96,7 +96,7 @@ public class SchemaHelperFactory { } // Check the class is a schema helper - if (!(schemaHelperObject instanceof SchemaHelper)) { + if (!(schemaHelperObject instanceof SchemaHelper schemaHelper)) { final var resultString = "Specified Apex context schema helper plugin class \"" + pluginClass + "\" does not implement the SchemaHelper interface"; LOGGER.warn(resultString); @@ -104,7 +104,6 @@ public class SchemaHelperFactory { } // The context schema helper to return - final var schemaHelper = (SchemaHelper) schemaHelperObject; // Lock and load the schema helper schemaHelper.init(owningEntityKey.getKey(), schema); diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java index 3d46e6a80..56539a1d7 100644 --- a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2020-2023 Nordix Foundation. + * Copyright (C) 2020-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ package org.onap.policy.apex.examples.grpc; +import static org.awaitility.Awaitility.await; + import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; @@ -28,6 +30,7 @@ import jakarta.ws.rs.core.Response; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; import org.slf4j.ext.XLogger; import org.slf4j.ext.XLoggerFactory; @@ -52,8 +55,12 @@ public class GrpcTestRestSimEndpoint { public Response dcaeClOutput(@QueryParam("timeout") final int timeout) throws IOException { String createSubscriptionRequest = Files.readString(Paths.get("src/main/resources/examples/events/APEXgRPC/CreateSubscriptionEvent.json")); - LOGGER.info("Create subscription request received: \n {}", createSubscriptionRequest); + LOGGER.info("Create subscription request received (on a timeout of {}): \n {} ", + timeout, createSubscriptionRequest); + await().pollDelay(4, TimeUnit.SECONDS) + .atMost(5, TimeUnit.SECONDS) + .until(() -> true); return Response.status(200).entity(createSubscriptionRequest).build(); } diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java index 46e0ea254..4dc638551 100644 --- a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestServerSim.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2020,2023 Nordix Foundation. + * Copyright (C) 2020, 2023-2024 Nordix Foundation. * Modifications Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,11 +33,11 @@ import org.onap.policy.simulators.CdsSimulator; */ public class GrpcTestServerSim { private static final String HOST = "localhost"; - private HttpServletServer restServer; - private CdsSimulator grpcServer; + private final HttpServletServer restServer; + private final CdsSimulator grpcServer; /** - * Instantiates a new REST simulator for DMaaP requests. + * Instantiates a new REST simulator for requests. * * @throws InterruptedException interrupted exception * @throws IOException io exception diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java index ee1744f0e..e6d71e1ff 100644 --- a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java @@ -41,6 +41,7 @@ import org.onap.policy.apex.service.engine.main.ApexMain; * CDS is used to send a final output Log event on POLICY_CL_MGT topic. */ class TestApexGrpcExample { + @Test void testGrpcExample() throws Exception { // @formatter:off @@ -78,18 +79,24 @@ class TestApexGrpcExample { String getLoggedEventUrl = "http://localhost:54321/GrpcTestRestSim/sim/event/getLoggedEvent"; // wait for success response code to be received, until a timeout - await().atMost(20000, TimeUnit.MILLISECONDS).until(() -> - 200 == client.target(getLoggedEventUrl).request("application/json").get().getStatus()); + await().atMost(50000, TimeUnit.MILLISECONDS) + .pollInterval(10000, TimeUnit.MILLISECONDS) + .until(() -> 200 == client.target(getLoggedEventUrl).request("application/json").get().getStatus()); + apexMain.shutdown(); + Response response = client.target(getLoggedEventUrl).request("application/json").get(); sim.tearDown(); + String responseEntity = response.readEntity(String.class); - String expectedLoggedOutputEvent = Files - .readString(Paths.get("src/main/resources/examples/events/APEXgRPC/LogEvent.json")).replaceAll("\r", ""); - String expectedStatusEvent = - Files.readString(Paths.get("src/main/resources/examples/events/APEXgRPC/CDSResponseStatusEvent.json")) - .replaceAll("\r", ""); + var logFileJson = "src/main/resources/examples/events/APEXgRPC/LogEvent.json"; + String expectedLoggedOutputEvent = Files.readString(Paths.get(logFileJson)).replaceAll("\r", ""); + + var cdsResponseJson = "src/main/resources/examples/events/APEXgRPC/CDSResponseStatusEvent.json"; + String expectedStatusEvent = Files.readString(Paths.get(cdsResponseJson)).replaceAll("\r", ""); + // Both LogEvent and CDSResponseStatusEvent are generated from the final state in the policy assertThat(responseEntity).contains(expectedStatusEvent).contains(expectedLoggedOutputEvent); + client.close(); } }
\ No newline at end of file diff --git a/model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyLogicReader.java b/model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyLogicReader.java index 8b0dec7b7..4a8780a4f 100644 --- a/model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyLogicReader.java +++ b/model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyLogicReader.java @@ -23,7 +23,6 @@ package org.onap.policy.apex.model.policymodel.handling; import static org.onap.policy.apex.model.basicmodel.concepts.AxConcept.WHITESPACE_REGEX; -import org.jetbrains.annotations.NotNull; import org.onap.policy.apex.model.basicmodel.concepts.AxKey; import org.onap.policy.apex.model.policymodel.concepts.AxLogic; import org.onap.policy.apex.model.policymodel.concepts.AxLogicReader; @@ -124,7 +123,7 @@ public class PolicyLogicReader implements AxLogicReader { return logicString.replaceAll(WHITESPACE_REGEX, ""); } - private @NotNull String getFullLogicFilePath(AxLogic axLogic) { + private String getFullLogicFilePath(AxLogic axLogic) { String fullLogicFilePath = logicPackage.replace(".", "/"); // Now, the logic should be in a subdirectory for the logic executor type diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/pom.xml b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/pom.xml index c46b26271..99864b304 100644 --- a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/pom.xml +++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/pom.xml @@ -1,7 +1,7 @@ <!-- ============LICENSE_START======================================================= Copyright (C) 2022 Bell Canada. All rights reserved. - Modifications Copyright (C) 2023 Nordix Foundation. + Modifications Copyright (C) 2023-2024 Nordix Foundation. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -33,8 +33,8 @@ <dependencies> <dependency> - <groupId>com.worldturner.medeia</groupId> - <artifactId>medeia-validator-gson</artifactId> + <groupId>com.networknt</groupId> + <artifactId>json-schema-validator</artifactId> </dependency> </dependencies> </project> diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelper.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelper.java index 4896e5d4a..0e8d5dfc8 100644 --- a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelper.java +++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/main/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelper.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2022 Bell Canada. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,18 +23,18 @@ package org.onap.policy.apex.plugins.context.schema.json; import com.google.gson.Gson; import com.google.gson.JsonElement; -import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import com.worldturner.medeia.api.SchemaSource; -import com.worldturner.medeia.api.StringInputSource; -import com.worldturner.medeia.api.StringSchemaSource; -import com.worldturner.medeia.api.gson.MedeiaGsonApi; -import com.worldturner.medeia.schema.validation.SchemaValidator; +import com.networknt.schema.InputFormat; +import com.networknt.schema.JsonSchema; +import com.networknt.schema.JsonSchemaFactory; +import com.networknt.schema.SpecVersionDetector; +import java.io.StringReader; import java.io.StringWriter; import java.util.List; import java.util.Map; import org.onap.policy.apex.context.ContextRuntimeException; import org.onap.policy.apex.context.impl.schema.AbstractSchemaHelper; +import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException; import org.onap.policy.apex.model.basicmodel.concepts.AxKey; import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema; @@ -44,16 +45,14 @@ public class JsonSchemaHelper extends AbstractSchemaHelper { private static final Gson gson = new Gson(); - private MedeiaGsonApi api = new MedeiaGsonApi(); - private SchemaValidator validator; + private JsonSchema jsonSchema; @Override public void init(final AxKey userKey, final AxContextSchema schema) { super.init(userKey, schema); try { - SchemaSource source = new StringSchemaSource(schema.getSchema()); - validator = api.loadSchema(source); + this.jsonSchema = getJsonSchema(schema.getSchema()); } catch (final Exception e) { final String resultSting = userKey.getId() + ": json context schema \"" + schema.getId() + "\" schema is invalid, schema: " + schema.getSchema(); @@ -86,8 +85,8 @@ public class JsonSchemaHelper extends AbstractSchemaHelper { return object; } var objectString = (String) object; - JsonReader reader = api.createJsonReader(validator, new StringInputSource(objectString)); - return gson.fromJson(reader, Object.class); + validate(objectString); + return gson.fromJson(new StringReader(objectString), Object.class); } @Override @@ -103,7 +102,8 @@ public class JsonSchemaHelper extends AbstractSchemaHelper { } private JsonElement validateAndDecode(Object schemaObject, StringWriter stringWriter) { - JsonWriter jsonWriter = api.createJsonWriter(validator, stringWriter); + validate(schemaObject); + JsonWriter jsonWriter = new JsonWriter(stringWriter); jsonWriter.setIndent(" "); // to enable pretty print JsonElement jsonObj = gson.toJsonTree(schemaObject); gson.toJson(jsonObj, jsonWriter); @@ -119,4 +119,27 @@ public class JsonSchemaHelper extends AbstractSchemaHelper { private boolean passThroughObject(final Object object) { return (object instanceof JsonElement || object instanceof Map || object instanceof List); } + + private JsonSchema getJsonSchema(String jsonSchema) { + var schemaMap = new Gson().fromJson(jsonSchema, Map.class); + if (schemaMap != null && schemaMap.containsKey("$schema")) { + var flag = SpecVersionDetector.detectOptionalVersion(schemaMap.get("$schema").toString()).orElse(null); + return JsonSchemaFactory.getInstance(flag).getSchema(jsonSchema); + } else { + throw new ApexRuntimeException("Schema is invalid"); + } + } + + private void validate(String json) { + var validations = this.jsonSchema.validate(json, InputFormat.JSON); + if (!validations.isEmpty()) { + StringBuilder errors = new StringBuilder(); + validations.forEach(m -> errors.append(m.toString()).append("\n")); + throw new ApexRuntimeException(errors.toString()); + } + } + + private void validate(Object object) { + validate(gson.toJson(object)); + } } diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperMarshalTest.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperMarshalTest.java index b129330ce..413037b97 100644 --- a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperMarshalTest.java +++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperMarshalTest.java @@ -26,7 +26,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import com.worldturner.medeia.api.ValidationFailedException; import java.util.ArrayList; import java.util.Map; import org.junit.jupiter.api.Test; @@ -103,8 +102,7 @@ class JsonSchemaHelperMarshalTest extends CommonTestData { var dataAsObject = coder.decode(COMMONHEADER, Map.class); dataAsObject.remove(TEST_ID); assertThatThrownBy(() -> validateAndMarshal(COMMONHEADERTYPE_DRAFT07, dataAsObject, true)) - .isInstanceOf(ValidationFailedException.class) - .hasMessageContaining("Required property testId is missing from object"); + .hasMessageContaining("required property 'testId' not found"); } /** diff --git a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperUnmarshalTest.java b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperUnmarshalTest.java index d0059f26f..f633b2d0f 100644 --- a/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperUnmarshalTest.java +++ b/plugins/plugins-context/plugins-context-schema/plugins-context-schema-json/src/test/java/org/onap/policy/apex/plugins/context/schema/json/JsonSchemaHelperUnmarshalTest.java @@ -25,7 +25,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.gson.JsonObject; -import com.worldturner.medeia.api.ValidationFailedException; import java.util.ArrayList; import java.util.Map; import org.junit.jupiter.api.Test; @@ -74,7 +73,8 @@ class JsonSchemaHelperUnmarshalTest extends CommonTestData { new AxContextSchema(new AxArtifactKey("JsonObject", VERSION), JSON, schemaDef); var jsonSchemaHelper = new JsonSchemaHelper(); assertThatThrownBy(() -> jsonSchemaHelper.init(testKey, jsonSchema)) - .isInstanceOf(ContextRuntimeException.class).hasMessageContaining("schema is invalid"); + .isInstanceOf(ContextRuntimeException.class) + .hasMessageContaining("schema is invalid"); } /** @@ -111,8 +111,7 @@ class JsonSchemaHelperUnmarshalTest extends CommonTestData { var dataAsObject = coder.decode(COMMONHEADER, JsonObject.class); dataAsObject.addProperty("requestId", "abcd"); assertThatThrownBy(() -> validateAndUnmarshal(COMMONHEADERTYPE_DRAFT07, dataAsObject)) - .isInstanceOf(ValidationFailedException.class) - .hasMessageContaining("Pattern ^[0-9]*-[0-9]*$ is not contained in text"); + .hasMessageContaining("does not match the regex pattern ^[0-9]*-[0-9]*$"); } /** @@ -137,8 +136,7 @@ class JsonSchemaHelperUnmarshalTest extends CommonTestData { var dataAsObject = coder.decode(COMMONHEADER, JsonObject.class); dataAsObject.remove(TEST_ID); assertThatThrownBy(() -> validateAndUnmarshal(COMMONHEADERTYPE_DRAFT07, dataAsObject)) - .isInstanceOf(ValidationFailedException.class) - .hasMessageContaining("Required property testId is missing from object"); + .hasMessageContaining("required property 'testId' not found"); } /** diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImplTest.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImplTest.java index caba093ce..34db034ed 100644 --- a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImplTest.java +++ b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/runtime/impl/EngineServiceImplTest.java @@ -32,7 +32,6 @@ import static org.junit.jupiter.api.Assertions.fail; import java.io.ByteArrayInputStream; import java.io.IOException; -import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -118,7 +117,7 @@ class EngineServiceImplTest { ParameterService.register(engineParameters); } - private static @NotNull ExecutorParameters getExecutorParameters(String lang) { + private static ExecutorParameters getExecutorParameters(String lang) { ExecutorParameters jsExecutorParameters = new ExecutorParameters(); jsExecutorParameters.setName(lang); jsExecutorParameters diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/runtime/impl/EngineWorkerTest.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/runtime/impl/EngineWorkerTest.java index 0716e0ad3..5082100e0 100644 --- a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/runtime/impl/EngineWorkerTest.java +++ b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/runtime/impl/EngineWorkerTest.java @@ -34,7 +34,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -125,7 +124,7 @@ class EngineWorkerTest { } - private static @NotNull ExecutorParameters getExecutorParameters(String lang) { + private static ExecutorParameters getExecutorParameters(String lang) { ExecutorParameters jsExecutorParameters = new ExecutorParameters(); jsExecutorParameters.setName(lang); jsExecutorParameters |