Async: NCMP Rest impl. including Request ID generation 18/127718/3
authorsourabh_sourabh <sourabh.sourabh@est.tech>
Sat, 12 Mar 2022 17:11:10 +0000 (22:41 +0530)
committersourabh_sourabh <sourabh.sourabh@est.tech>
Mon, 14 Mar 2022 17:16:19 +0000 (22:46 +0530)
- In case of invalid topic return http status 400 with error message
- Unit test is modified to handle/validate InvalidTopicException

Issue-ID: CPS-828
Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
Change-Id: I05645c92ccebb8aa422a47f6edcde7b64088a118

cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandler.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidTopicException.java [new file with mode: 0644]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy

index 2495f36..0843e97 100755 (executable)
@@ -24,6 +24,7 @@ import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.impl.exception.DmiRequestException;
+import org.onap.cps.ncmp.api.impl.exception.InvalidTopicException;
 import org.onap.cps.ncmp.api.impl.exception.NcmpException;
 import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException;
 import org.onap.cps.ncmp.rest.controller.NetworkCmProxyController;
@@ -65,7 +66,8 @@ public class NetworkCmProxyRestExceptionHandler {
         return buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, exception);
     }
 
-    @ExceptionHandler({DmiRequestException.class, DataValidationException.class, HttpMessageNotReadableException.class})
+    @ExceptionHandler({DmiRequestException.class, DataValidationException.class, HttpMessageNotReadableException.class,
+            InvalidTopicException.class})
     public static ResponseEntity<Object> handleDmiRequestExceptions(final Exception exception) {
         return buildErrorResponse(HttpStatus.BAD_REQUEST, exception);
     }
index e923ce4..76d4cef 100755 (executable)
@@ -42,11 +42,11 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.logging.log4j.util.Strings;
 import org.onap.cps.api.CpsAdminService;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.api.CpsModuleService;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+import org.onap.cps.ncmp.api.impl.exception.InvalidTopicException;
 import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException;
 import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
 import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations;
@@ -303,8 +303,14 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
             yangModelCmHandle.getId());
     }
 
-    private static boolean isValidTopicName(final String topicName) {
-        return Strings.isNotEmpty(topicName) && TOPIC_NAME_PATTERN.matcher(topicName).matches();
+    private static boolean hasTopicParameter(final String topicName) {
+        if (topicName == null) {
+            return false;
+        }
+        if (TOPIC_NAME_PATTERN.matcher(topicName).matches()) {
+            return true;
+        }
+        throw new InvalidTopicException("Topic name " + topicName + " is invalid", "invalid topic");
     }
 
     private Map<String, Object> buildDmiResponse(final String requestId) {
@@ -319,7 +325,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
                                                        final DmiOperations.DataStoreEnum dataStore,
                                                        final String optionsParamInQuery,
                                                        final String topicParamInQuery) {
-        final boolean processAsynchronously = isValidTopicName(topicParamInQuery);
+        final boolean processAsynchronously = hasTopicParameter(topicParamInQuery);
         if (processAsynchronously) {
             final String resourceDataRequestId = UUID.randomUUID().toString();
             return ResponseEntity.status(HttpStatus.OK)
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidTopicException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidTopicException.java
new file mode 100644 (file)
index 0000000..b56ca7b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  ============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.api.impl.exception;
+
+import lombok.Getter;
+
+public class InvalidTopicException extends RuntimeException {
+
+    @Getter
+    final String details;
+
+    /**
+     * Constructor.
+     *
+     * @param message the error message
+     * @param details the error details
+     */
+    public InvalidTopicException(final String message, final String details) {
+        super(message);
+        this.details = details;
+    }
+}
index e6d18d9..c21d7e7 100644 (file)
@@ -22,6 +22,7 @@
 
 package org.onap.cps.ncmp.api.impl
 
+import org.onap.cps.ncmp.api.impl.exception.InvalidTopicException
 import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
 import spock.lang.Shared
@@ -217,7 +218,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             exceptionThrown.details.contains('NOK-json')
     }
 
-    def 'Get resource data for operational from DMI with empty topic sync request.'() {
+    def 'DMI Operational data request with #scenario'() {
         given: 'cps data service returns valid data node'
             mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
                     cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
@@ -227,14 +228,14 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
         when: 'get resource data is called data operational with blank topic'
             def responseData = objectUnderTest.getResourceDataOperationalForCmHandle('', '',
                     '', '', emptyTopic)
-        then: '(synchronous) the dmi response is expected'
-            assert responseData == '{dmi-response}'
+        then: 'a invalid topic exception is thrown'
+            thrown(InvalidTopicException)
         where: 'the following parameters are used'
-            scenario             | emptyTopic
-            'No topic in url'    | ''
-            'Null topic in url'  | null
-            'Empty topic in url' | '\"\"'
-            'Blank topic in url' | ' '
+            scenario                               | emptyTopic
+            'no topic value in url'                | ''
+            'empty topic value in url'             | '\"\"'
+            'blank topic value in url'             | ' '
+            'invalid non-empty topic value in url' | '1_5_*_#'
     }
 
     def 'Get resource data for data operational from DMI with valid topic i.e. async request.'() {
@@ -263,7 +264,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             assert responseData.body.requestId.length() > 0
     }
 
-    def 'Get resource data for pass through running from DMI sync request where #scenario.'() {
+    def 'DMI pass through running data request with #scenario'() {
         given: 'cps data service returns valid data node'
             mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
                     cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
@@ -273,14 +274,14 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
         when: 'get resource data is called for data operational with valid topic'
             def responseData = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('',
                     '', '', '', emptyTopic)
-        then: '(synchronous) the dmi response is expected'
-            assert responseData == '{dmi-response}'
+        then: 'a invalid topic exception is thrown'
+            thrown(InvalidTopicException)
         where: 'the following parameters are used'
-            scenario             | emptyTopic
-            'No topic in url'    | ''
-            'Null topic in url'  | null
-            'Empty topic in url' | '\"\"'
-            'Blank topic in url' | ' '
+            scenario                               | emptyTopic
+            'no topic value in url'                | ''
+            'empty topic value in url'             | '\"\"'
+            'blank topic value in url'             | ' '
+            'invalid non-empty topic value in url' | '1_5_*_#'
     }
 
     def 'Getting Yang Resources.'() {