diff options
author | DylanB95EST <dylan.byrne@est.tech> | 2022-02-21 12:57:08 +0000 |
---|---|---|
committer | Bruno Sakoto <bruno.sakoto@bell.ca> | 2022-02-28 21:52:25 +0000 |
commit | d042fcdae75be100f840b6313e078eab278d87ef (patch) | |
tree | ee5bba86b3ba00205334a1fe6ca41c0824097afd /cps-ncmp-rest | |
parent | e0643ab5130dde375c229989e216341e623a9c55 (diff) |
NCMP Java API depends on NCM-Rest-API (cyclic) through json properties on Java API
Using POJO and new converter class instead
of previous object mapper
Issue-ID: CPS-893
Change-Id: I75531f386f08cb172d2901a4bbe97ae22cc5937e
Signed-off-by: DylanB95EST <dylan.byrne@est.tech>
Diffstat (limited to 'cps-ncmp-rest')
13 files changed, 236 insertions, 67 deletions
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml index cda6ca3ac5..fd02b6e564 100644 --- a/cps-ncmp-rest/docs/openapi/components.yaml +++ b/cps-ncmp-rest/docs/openapi/components.yaml @@ -38,12 +38,15 @@ components: dmiPlugin: type: string example: my-dmi-plugin + default: "" dmiDataPlugin: type: string example: my-dmi-data-plugin + default: "" dmiModelPlugin: type: string example: my-dmi-model-plugin + default: "" createdCmHandles: type: array items: diff --git a/cps-ncmp-rest/pom.xml b/cps-ncmp-rest/pom.xml index b3ae81be58..97305cfe98 100644 --- a/cps-ncmp-rest/pom.xml +++ b/cps-ncmp-rest/pom.xml @@ -61,6 +61,14 @@ <groupId>io.swagger.core.v3</groupId> <artifactId>swagger-annotations</artifactId> </dependency> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct</artifactId> + </dependency> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct-processor</artifactId> + </dependency> <!-- T E S T D E P E N D E N C I E S --> <dependency> <groupId>org.codehaus.groovy</groupId> diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java index 9e888fb1c5..36991952c8 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java @@ -21,12 +21,9 @@ package org.onap.cps.ncmp.rest.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; import javax.validation.Valid; import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; -import org.onap.cps.ncmp.api.models.DmiPluginRegistration; import org.onap.cps.ncmp.rest.api.NetworkCmProxyInventoryApi; import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration; import org.springframework.http.HttpStatus; @@ -40,7 +37,7 @@ import org.springframework.web.bind.annotation.RestController; public class NetworkCmProxyInventoryController implements NetworkCmProxyInventoryApi { private final NetworkCmProxyDataService networkCmProxyDataService; - private final ObjectMapper objectMapper; + private final RestInputMapper restInputMapper; /** * Update DMI Plugin Registration (used for first registration also). @@ -49,14 +46,11 @@ public class NetworkCmProxyInventoryController implements NetworkCmProxyInventor @Override public ResponseEntity<Void> updateDmiPluginRegistration( final @Valid RestDmiPluginRegistration restDmiPluginRegistration) { - final DmiPluginRegistration dmiPluginRegistration = - convertRestObjectToJavaApiObject(restDmiPluginRegistration); - networkCmProxyDataService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration); + networkCmProxyDataService.updateDmiRegistrationAndSyncModule( + restInputMapper.toDmiPluginRegistration(restDmiPluginRegistration)); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } - private DmiPluginRegistration convertRestObjectToJavaApiObject( - final RestDmiPluginRegistration restDmiPluginRegistration) { - return objectMapper.convertValue(restDmiPluginRegistration, DmiPluginRegistration.class); - } } + + diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java new file mode 100644 index 0000000000..d38204cf1b --- /dev/null +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/RestInputMapper.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.rest.controller; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.NullValueMappingStrategy; +import org.mapstruct.NullValuePropertyMappingStrategy; +import org.onap.cps.ncmp.api.models.CmHandle; +import org.onap.cps.ncmp.api.models.DmiPluginRegistration; +import org.onap.cps.ncmp.rest.model.RestCmHandle; +import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration; + +@Mapper(componentModel = "spring", nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT) +public interface RestInputMapper { + + DmiPluginRegistration toDmiPluginRegistration(final RestDmiPluginRegistration restDmiPluginRegistration); + + @Mappings({ + @Mapping(source = "cmHandle", target = "cmHandleID"), + @Mapping(source = "cmHandleProperties", target = "dmiProperties"), + @Mapping(source = "publicCmHandleProperties", target = "publicProperties") + }) + CmHandle toCmHandle(final RestCmHandle restCmHandle); + +} diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java index 7dc6284fcc..fd01096e19 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java @@ -33,6 +33,7 @@ import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.spi.exceptions.DataValidationException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -73,8 +74,8 @@ public class NetworkCmProxyRestExceptionHandler { return buildErrorResponse(HttpStatus.BAD_REQUEST, exception); } - @ExceptionHandler({DataValidationException.class}) - public static ResponseEntity<Object> handleDataValidatedExceptions(final DataValidationException exception) { + @ExceptionHandler({DataValidationException.class, HttpMessageNotReadableException.class}) + public static ResponseEntity<Object> handleDataValidatedExceptions(final Exception exception) { return buildErrorResponse(HttpStatus.BAD_REQUEST, exception); } diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy index 3c603ed425..079554a22d 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy @@ -24,8 +24,9 @@ package org.onap.cps.ncmp.rest.controller import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.TestUtils import org.onap.cps.ncmp.api.NetworkCmProxyDataService -import org.onap.cps.ncmp.api.models.CmHandle import org.onap.cps.ncmp.api.models.DmiPluginRegistration +import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration +import org.onap.cps.utils.JsonObjectMapper import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value @@ -47,46 +48,51 @@ class NetworkCmProxyInventoryControllerSpec extends Specification { @SpringBean NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock() + @SpringBean + RestInputMapper restInputMapper = Mock() + + DmiPluginRegistration mockDmiPluginRegistration = Mock() + + JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) + @Value('${rest.api.ncmp-inventory-base-path}/v1') def ncmpBasePathV1 - def 'Register CM Handle Event' () { - given: 'jsonData' - def jsonData = TestUtils.getResourceFileContent('dmi-registration.json') - when: 'post request is performed' + def 'Dmi plugin registration #scenario' () { + given: 'a dmi plugin registration with #scenario' + def jsonData = TestUtils.getResourceFileContent(dmiRegistrationJson) + and: 'the expected rest input as an object' + def expectedRestDmiPluginRegistration = jsonObjectMapper.convertJsonString(jsonData, RestDmiPluginRegistration) + and: 'the converter returns a dmi registration (only for the expected input object)' + restInputMapper.toDmiPluginRegistration(expectedRestDmiPluginRegistration) >> mockDmiPluginRegistration + when: 'post request is performed & registration is called with correct DMI plugin information' def response = mvc.perform( post("$ncmpBasePathV1/ch") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonData) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonData) ).andReturn().response - then: 'the cm handles are registered with the service' - 1 * mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule(_) - and: 'response status is No Content' - response.status == HttpStatus.NO_CONTENT.value() + then: 'the converted object is forwarded to the registration service' + 1 * mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule(mockDmiPluginRegistration) + and: 'response status is no content' + response.status == HttpStatus.NO_CONTENT.value() + where: 'the following registration json is used' + scenario | dmiRegistrationJson + 'multiple services, added, updated and removed cm handles and many properties' | 'dmi_registration_all_singing_and_dancing.json' + 'updated cm handle with updated/new and removed properties' | 'dmi_registration_updates_only.json' + 'without any properties' | 'dmi_registration_without_properties.json' } - def 'Dmi plugin registration with #scenario' () { - given: 'jsonData, cmHandle, & DmiPluginRegistration' - def jsonData = TestUtils.getResourceFileContent('dmi_registration_combined_valid.json' ) - def cmHandle = new CmHandle(cmHandleID : 'example-name') - def expectedDmiPluginRegistration = new DmiPluginRegistration( - dmiPlugin: 'service1', - dmiDataPlugin: '', - dmiModelPlugin: '', - createdCmHandles: [cmHandle]) + def 'Dmi plugin registration with invalid json' () { + given: 'a dmi plugin registration with #scenario' + def jsonDataWithUndefinedDataLabel = '{"notAdmiPlugin":""}' when: 'post request is performed & registration is called with correct DMI plugin information' def response = mvc.perform( post("$ncmpBasePathV1/ch") .contentType(MediaType.APPLICATION_JSON) - .content(jsonData) + .content(jsonDataWithUndefinedDataLabel) ).andReturn().response - then: 'no NcmpException is thrown & updateDmiRegistrationAndSyncModule is called with correct parameters' - 1 * mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule({ - it.getDmiPlugin() == expectedDmiPluginRegistration.getDmiPlugin() - it.getDmiDataPlugin() == expectedDmiPluginRegistration.getDmiDataPlugin() - it.getDmiModelPlugin() == expectedDmiPluginRegistration.getDmiModelPlugin() - it.getCreatedCmHandles().get(0).getCmHandleID() == expectedDmiPluginRegistration.getCreatedCmHandles().get(0).getCmHandleID() - }) + then: 'response status is bad request' + response.status == HttpStatus.BAD_REQUEST.value() } -} +} diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy new file mode 100644 index 0000000000..c48a8ed360 --- /dev/null +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/RestInputMapperSpec.groovy @@ -0,0 +1,64 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.rest.controller + +import org.mapstruct.factory.Mappers +import org.onap.cps.ncmp.rest.model.RestCmHandle +import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration +import spock.lang.Specification + +class RestInputMapperSpec extends Specification { + + def objectUnderTest = Mappers.getMapper(RestInputMapper.class) + + def 'Convert a created REST CM Handle Input to an NCMP Service CM Handle with #scenario'() { + given: 'a rest cm handle input' + def inputRestCmHandle = new RestCmHandle(cmHandle : 'example-id', cmHandleProperties: dmiProperties, + publicCmHandleProperties: publicProperties) + def restDmiPluginRegistration = new RestDmiPluginRegistration( + createdCmHandles: [inputRestCmHandle]) + when: 'to plugin dmi registration is called' + def result = objectUnderTest.toDmiPluginRegistration(restDmiPluginRegistration) + then: 'the result returns the correct number of cm handles' + result.createdCmHandles.size() == 1 + and: 'the converted cm handle has the same id' + result.createdCmHandles[0].cmHandleID == 'example-id' + and: '(empty) properties are converted correctly' + result.createdCmHandles[0].dmiProperties == expectedDmiProperties + result.createdCmHandles[0].publicProperties == expectedPublicProperties + where: 'the following parameters are used' + scenario | dmiProperties | publicProperties || expectedDmiProperties | expectedPublicProperties + 'dmi and public properties' | ['Property-Example': 'example property'] | ['Public-Property-Example': 'public example property'] || ['Property-Example': 'example property'] | ['Public-Property-Example': 'public example property'] + 'no properties' | null | null || [:] | [:] + } + + def 'Handling empty dmi registration'() { + given: 'a rest cm handle input without any cm handles' + def restDmiPluginRegistration = new RestDmiPluginRegistration() + when: 'to plugin dmi registration is called' + def result = objectUnderTest.toDmiPluginRegistration(restDmiPluginRegistration) + then: 'unspecified lists remain as empty lists' + assert result.createdCmHandles == [] + assert result.updatedCmHandles == [] + assert result.removedCmHandles == [] + } + +} diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy index 35544d9411..306f546f32 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy @@ -27,6 +27,7 @@ import org.onap.cps.TestUtils import org.onap.cps.ncmp.api.NetworkCmProxyDataService import org.onap.cps.ncmp.api.impl.exception.DmiRequestException import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException +import org.onap.cps.ncmp.rest.controller.RestInputMapper import org.onap.cps.spi.exceptions.CpsException import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.utils.JsonObjectMapper @@ -61,6 +62,9 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { @SpringBean JsonObjectMapper jsonObjectMapper = Stub() + @SpringBean + RestInputMapper restInputMapper = Mock() + @Value('${rest.api.ncmp-base-path}') def basePathNcmp @@ -105,17 +109,17 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { } def setupTestException(exception, apiType) { - if (NCMP.equals(apiType)) { + if (NCMP == apiType) { mockNetworkCmProxyDataService.getYangResourcesModuleReferences(*_) >> { throw exception } } mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule(*_) >> { throw exception } } def performTestRequest(apiType) { - if (NCMP.equals(apiType)) { + if (NCMP == apiType) { return mvc.perform(get("$dataNodeBaseEndpointNcmp/ch/testCmHandle/modules")).andReturn().response } - def jsonData = TestUtils.getResourceFileContent('dmi-registration.json') + def jsonData = TestUtils.getResourceFileContent('dmi_registration_all_singing_and_dancing.json') return mvc.perform(post("$dataNodeBaseEndpointNcmpInventory/ch").contentType(MediaType.APPLICATION_JSON).content(jsonData)).andReturn().response } diff --git a/cps-ncmp-rest/src/test/resources/dmi-registration.json b/cps-ncmp-rest/src/test/resources/dmi-registration.json deleted file mode 100644 index 4f27e11843..0000000000 --- a/cps-ncmp-rest/src/test/resources/dmi-registration.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "dmiPlugin": "onap-dmi-plugin", - "createdCmHandles": [ - { - "cmHandle": "example-name", - "cmHandleProperties": { - "subSystemId" : "system-001" - }, - "publicCmHandleProperties": { - "area" : "south" - } - } - ] -}
\ No newline at end of file diff --git a/cps-ncmp-rest/src/test/resources/dmi_registration_all_singing_and_dancing.json b/cps-ncmp-rest/src/test/resources/dmi_registration_all_singing_and_dancing.json new file mode 100644 index 0000000000..fd8b56b02d --- /dev/null +++ b/cps-ncmp-rest/src/test/resources/dmi_registration_all_singing_and_dancing.json @@ -0,0 +1,43 @@ +{ + "dmiDataPlugin":"service2", + "dmiModelPlugin":"service3", + "createdCmHandles":[ + { + "cmHandle":"ch1(new)", + "cmHandleProperties":{ + "dmiProp1":"ch1-dmi1", + "dmiProp2":"ch1-dmi2" + }, + "publicCmHandleProperties":{ + "pubProp1":"ch1-pub1", + "pubProp2":"ch1-pub2" + } + }, + { + "cmHandle":"ch2(new)", + "cmHandleProperties":{ + "dmiProp1":"ch2-dmi1", + "dmiProp2":"ch2-dmi2" + }, + "publicCmHandleProperties":{ + "pubProp1":"ch2-pub1", + "pubProp2":"ch2-pub2" + } + } + ], + "updatedCmHandles":[ + { + "cmHandle":"ch3(upd)", + "cmHandleProperties":{ + "dmiProp1":"ch3-dmi1" + }, + "publicCmHandleProperties":{ + "pubProp2":"ch3-pub1" + } + } + ], + "removedCmHandles":[ + "ch4", + "ch5" + ] +} diff --git a/cps-ncmp-rest/src/test/resources/dmi_registration_combined_valid.json b/cps-ncmp-rest/src/test/resources/dmi_registration_combined_valid.json deleted file mode 100644 index bded4f215c..0000000000 --- a/cps-ncmp-rest/src/test/resources/dmi_registration_combined_valid.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "dmiPlugin": "service1", - "dmiDataPlugin": "", - "dmiModelPlugin": "", - "createdCmHandles": [{ - "cmHandle": "example-name" - }] -}
\ No newline at end of file diff --git a/cps-ncmp-rest/src/test/resources/dmi_registration_updates_only.json b/cps-ncmp-rest/src/test/resources/dmi_registration_updates_only.json new file mode 100644 index 0000000000..58a1a9836b --- /dev/null +++ b/cps-ncmp-rest/src/test/resources/dmi_registration_updates_only.json @@ -0,0 +1,12 @@ +{ + "dmiPlugin": "service1", + "updatedCmHandles":[ + { + "cmHandle":"ch3(upd)", + "cmHandleProperties":{ + "dmiProp1":"ch3-dmi1", + "dmiProp2":null + } + } + ] +} diff --git a/cps-ncmp-rest/src/test/resources/dmi_registration_without_properties.json b/cps-ncmp-rest/src/test/resources/dmi_registration_without_properties.json new file mode 100644 index 0000000000..395c098d21 --- /dev/null +++ b/cps-ncmp-rest/src/test/resources/dmi_registration_without_properties.json @@ -0,0 +1,10 @@ +{ + "dmiPlugin":"", + "dmiDataPlugin":"service2", + "dmiModelPlugin":"service3", + "createdCmHandles":[ + { + "cmHandle": "ch1(new)" + } + ] +} |