From cd7f9d1d7030bfcacf7173d80d58d0a7c2fc5e71 Mon Sep 17 00:00:00 2001 From: seanbeirne Date: Tue, 18 Nov 2025 17:11:17 +0000 Subject: [PATCH] Bug: ProvMnS error handling returning all DMI error responses as 500 Issue-ID: CPS-3048 Change-Id: I9bc30f4f09664c331e396cb4aa18c90be3475f7c Signed-off-by: seanbeirne --- .../org/onap/cps/ncmp/impl/dmi/DmiRestClient.java | 30 ++++++++++++++-------- .../impl/dmi/DmiRestClientIntegrationSpec.groovy | 2 +- .../ncmp/provmns/ProvMnSRestApiSpec.groovy | 9 +++---- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java index 26f46638e3..17693a04c4 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java @@ -46,6 +46,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientRequestException; import org.springframework.web.reactive.function.client.WebClientResponseException; @@ -131,8 +132,7 @@ public class DmiRestClient { .get() .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables()) .headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION)) - .retrieve() - .toEntity(Object.class) + .exchangeToMono(this::createIdenticalResponseForClient) .block(); } @@ -152,8 +152,7 @@ public class DmiRestClient { .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables()) .headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION)) .bodyValue(body) - .retrieve() - .toEntity(Object.class) + .exchangeToMono(this::createIdenticalResponseForClient) .block(); } @@ -176,8 +175,7 @@ public class DmiRestClient { .headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION)) .contentType(MediaType.parseMediaType(contentType)) .bodyValue(body) - .retrieve() - .toEntity(Object.class) + .exchangeToMono(this::createIdenticalResponseForClient) .block(); } @@ -226,12 +224,11 @@ public class DmiRestClient { } /** - * Sends a synchronous (blocking) DELETE operation to the DMI with a JSON body without error mapping. + * Sends a synchronous (blocking) DELETE operation to the DMI without error mapping. * * @param requiredDmiService Determines if the required service is for a data or model operation. * @param urlTemplateParameters The DMI resource URL template with variables. - * @return ResponseEntity from the DMI Plugin - * @throws DmiClientRequestException If there is an error during the DMI request. + * @return ResponseEntity containing the response from the DMI. * */ public ResponseEntity synchronousDeleteOperation(final RequiredDmiService requiredDmiService, @@ -240,8 +237,7 @@ public class DmiRestClient { .delete() .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables()) .headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION)) - .retrieve() - .toEntity(Object.class) + .exchangeToMono(this::createIdenticalResponseForClient) .block(); } @@ -276,4 +272,16 @@ public class DmiRestClient { UNKNOWN_ERROR); } + private Mono> createIdenticalResponseForClient(final ClientResponse clientResponse) { + final HttpStatus status = (HttpStatus) clientResponse.statusCode(); + return clientResponse.bodyToMono(String.class) + .defaultIfEmpty("") + .map(body -> { + return ResponseEntity + .status(status) + .headers(clientResponse.headers().asHttpHeaders()) + .body(body); + }); + } + } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientIntegrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientIntegrationSpec.groovy index f5b9835e7d..ae09faea2b 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientIntegrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientIntegrationSpec.groovy @@ -53,7 +53,7 @@ class DmiRestClientIntegrationSpec extends Specification { } def 'Synchronous DMI #method request.'() { - given: 'Web Server wil return OK response' + given: 'Web Server will return OK response' mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.OK.value)) when: 'synchronous #method request is made' def result diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/provmns/ProvMnSRestApiSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/provmns/ProvMnSRestApiSpec.groovy index 698ff1ac76..78ae3d03cb 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/provmns/ProvMnSRestApiSpec.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/provmns/ProvMnSRestApiSpec.groovy @@ -38,9 +38,8 @@ class ProvMnSRestApiSpec extends CpsIntegrationSpecBase{ given: 'a registered cm handle' dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2'] registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, '/A=1/B=2/C=3') - expect: 'not implemented response on GET endpoint' - mvc.perform(get("/ProvMnS/v1/A=1/B=2/C=3")) - .andExpect(status().is2xxSuccessful()) + expect: 'an OK response on GET endpoint' + mvc.perform(get("/ProvMnS/v1/A=1/B=2/C=3")).andExpect(status().isOk()) cleanup: 'deregister CM handles' deregisterCmHandle(DMI1_URL, 'ch-1') } @@ -50,7 +49,7 @@ class ProvMnSRestApiSpec extends CpsIntegrationSpecBase{ dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2'] registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, '/A=1/B=2/C=3') def jsonBody = jsonObjectMapper.asJsonString(new ResourceOneOf('test')) - expect: 'not implemented response on PUT endpoint' + expect: 'an OK response on PUT endpoint' mvc.perform(put("/ProvMnS/v1/A=1/B=2/C=3") .contentType(MediaType.APPLICATION_JSON) .content(jsonBody)) @@ -64,7 +63,7 @@ class ProvMnSRestApiSpec extends CpsIntegrationSpecBase{ dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2'] registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, '/A=1/B=2/C=3') def jsonBody = jsonObjectMapper.asJsonString([new PatchItem(op: 'REMOVE', path: 'someUriLdnFirstPart')]) - expect: 'not implemented response on PATCH endpoint' + expect: 'an OK response on PATCH endpoint' mvc.perform(patch("/ProvMnS/v1/A=1/B=2/C=3") .contentType(new MediaType('application', 'json-patch+json')) .content(jsonBody)) -- 2.16.6