Give better messages than NPE for missing data 62/117562/1
authorJim Hahn <jrh3@att.com>
Fri, 5 Feb 2021 20:16:38 +0000 (15:16 -0500)
committerJim Hahn <jrh3@att.com>
Fri, 5 Feb 2021 20:17:25 +0000 (15:17 -0500)
When data is not available to actor operations, an NPE is generally
thrown.  Modified the code to provide more info about what is missing
than simply NPE.

Issue-ID: POLICY-2913
Change-Id: Ic56376ef5fdd0f2e46c2996405fff9aafa3692b9
Signed-off-by: Jim Hahn <jrh3@att.com>
controlloop/common/controller-usecases/src/main/java/org/onap/policy/drools/apps/controller/usecases/step/Step2.java
controlloop/common/controller-usecases/src/test/java/org/onap/policy/drools/apps/controller/usecases/step/Step2Test.java

index ca7b63f..dbdc6b9 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP
  * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -285,16 +285,17 @@ public class Step2 extends Step {
 
     protected CloudRegion getCloudRegion() {
         AaiCqResponse aaicq = getCustomQueryData();
-        return aaicq.getDefaultCloudRegion();
+        return verifyNotNull("default cloud region in A&AI response", aaicq.getDefaultCloudRegion());
     }
 
     protected Tenant getTenant() {
         AaiCqResponse aaicq = getCustomQueryData();
-        return aaicq.getDefaultTenant();
+        return verifyNotNull("default tenant in A&AI response", aaicq.getDefaultTenant());
     }
 
     protected StandardCoderObject getPnf() {
-        return stepContext.getProperty(AaiGetPnfOperation.getKey(getTargetEntity()));
+        String target = getTargetEntity();
+        return verifyNotNull("PNF for " + target, stepContext.getProperty(AaiGetPnfOperation.getKey(target)));
     }
 
     protected GenericVnf getResourceVnf() {
@@ -305,23 +306,25 @@ public class Step2 extends Step {
         verifyNotNull("Target resource ID", resourceId);
 
         AaiCqResponse aaicq = getCustomQueryData();
-        return aaicq.getGenericVnfByModelInvariantId(resourceId);
+        return verifyNotNull("VNF for " + resourceId, aaicq.getGenericVnfByModelInvariantId(resourceId));
     }
 
     protected ServiceInstance getService() {
         AaiCqResponse aaicq = getCustomQueryData();
-        return aaicq.getServiceInstance();
+        return verifyNotNull("service instance in A&AI response", aaicq.getServiceInstance());
     }
 
     protected ModelVer getServiceModel() {
         AaiCqResponse aaicq = getCustomQueryData();
-        ServiceInstance service = aaicq.getServiceInstance();
-        return aaicq.getModelVerByVersionId(service.getModelVersionId());
+        ServiceInstance service = getService();
+        String modelVersionId = verifyNotNull("service model version ID in A&AI response", service.getModelVersionId());
+        return verifyNotNull("model version for service in A&AI response",
+                        aaicq.getModelVerByVersionId(modelVersionId));
     }
 
     protected Vserver getVServer() {
         AaiCqResponse aaicq = getCustomQueryData();
-        return aaicq.getVserver();
+        return verifyNotNull("vserver in A&AI response", aaicq.getVserver());
     }
 
     /**
@@ -329,7 +332,7 @@ public class Step2 extends Step {
      * within the step's context.
      */
     protected String getTargetEntity() {
-        return stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY);
+        return verifyNotNull("A&AI target entity", stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY));
     }
 
     protected GenericVnf getVnf() {
@@ -340,13 +343,17 @@ public class Step2 extends Step {
         verifyNotNull(TARGET_MODEL_INVARIANT_ID, modelInvariantId);
 
         AaiCqResponse aaicq = getCustomQueryData();
-        return aaicq.getGenericVnfByVfModuleModelInvariantId(modelInvariantId);
+        return verifyNotNull("generic VNF in A&AI response for " + modelInvariantId,
+                        aaicq.getGenericVnfByVfModuleModelInvariantId(modelInvariantId));
     }
 
     protected ModelVer getVnfModel() {
         GenericVnf vnf = getVnf();
+        String modelVersionId =
+                        verifyNotNull("model version ID for generic VNF in A&AI response", vnf.getModelVersionId());
         AaiCqResponse aaicq = getCustomQueryData();
-        return aaicq.getModelVerByVersionId(vnf.getModelVersionId());
+        return verifyNotNull("model version for generic VNF in A&AI response",
+                        aaicq.getModelVerByVersionId(modelVersionId));
     }
 
     protected String getVserverLink() {
@@ -401,7 +408,7 @@ public class Step2 extends Step {
 
     protected GenericVnf getDefaultGenericVnf() {
         AaiCqResponse aaicq = getCustomQueryData();
-        return aaicq.getDefaultGenericVnf();
+        return verifyNotNull("generic VNF in A&AI response", aaicq.getDefaultGenericVnf());
     }
 
     protected AaiCqResponse getCustomQueryData() {
@@ -420,11 +427,13 @@ public class Step2 extends Step {
         stepContext.setProperty(OperationProperties.DATA_VF_COUNT, vfcount);
     }
 
-    protected void verifyNotNull(String propName, Object value) {
+    protected <T> T verifyNotNull(String propName, T value) {
         if (value == null) {
             throw new IllegalArgumentException(
                             "missing " + propName + " for " + getActorName() + "." + getOperationName());
         }
+
+        return value;
     }
 
     protected static String stripPrefix(String resourceLink, int ncomponents) {
index 8119019..1fe3653 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP
  * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -53,6 +53,7 @@ import org.onap.aai.domain.yang.GenericVnf;
 import org.onap.aai.domain.yang.ModelVer;
 import org.onap.aai.domain.yang.ServiceInstance;
 import org.onap.aai.domain.yang.Tenant;
+import org.onap.aai.domain.yang.Vserver;
 import org.onap.policy.aai.AaiCqResponse;
 import org.onap.policy.common.utils.coder.StandardCoderObject;
 import org.onap.policy.controlloop.VirtualControlLoopEvent;
@@ -221,6 +222,10 @@ public class Step2Test {
 
         step.setProperties();
         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_CLOUD_REGION, data);
+
+        when(aaicq.getDefaultCloudRegion()).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getCloudRegion())
+                        .withMessageContaining("missing default cloud region in A&AI response");
     }
 
     @Test
@@ -231,6 +236,10 @@ public class Step2Test {
 
         step.setProperties();
         verify(policyOperation).setProperty(OperationProperties.AAI_DEFAULT_TENANT, data);
+
+        when(aaicq.getDefaultTenant()).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getTenant())
+                        .withMessageContaining("missing default tenant in A&AI response");
     }
 
     @Test
@@ -242,6 +251,10 @@ public class Step2Test {
 
         step.setProperties();
         verify(policyOperation).setProperty(OperationProperties.AAI_PNF, data);
+
+        when(stepContext.getProperty(AaiGetPnfOperation.getKey(MY_TARGET))).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getPnf())
+                        .withMessageContaining("missing PNF for my-target");
     }
 
     @Test
@@ -254,6 +267,10 @@ public class Step2Test {
         step.setProperties();
         verify(policyOperation).setProperty(OperationProperties.AAI_RESOURCE_VNF, data);
 
+        when(aaicq.getGenericVnfByModelInvariantId("my-resource")).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getResourceVnf())
+                        .withMessageContaining("missing VNF for my-resource");
+
         // missing resource ID
         params.getTargetEntityIds().put(Step2.TARGET_RESOURCE_ID, null);
         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
@@ -275,6 +292,10 @@ public class Step2Test {
 
         step.setProperties();
         verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE, data);
+
+        when(aaicq.getServiceInstance()).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getService())
+                        .withMessageContaining("missing service instance in A&AI response");
     }
 
     @Test
@@ -289,6 +310,41 @@ public class Step2Test {
 
         step.setProperties();
         verify(policyOperation).setProperty(OperationProperties.AAI_SERVICE_MODEL, data);
+
+        when(aaicq.getModelVerByVersionId("my-service-version")).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
+                        .withMessageContaining("missing model version for service in A&AI response");
+
+        service.setModelVersionId(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
+                        .withMessageContaining("missing service model version ID in A&AI response");
+
+        when(aaicq.getServiceInstance()).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getServiceModel())
+                        .withMessageContaining("missing service instance in A&AI response");
+    }
+
+    @Test
+    public void testGetVserver() {
+        Vserver vserver = new Vserver();
+        when(aaicq.getVserver()).thenReturn(vserver);
+
+        assertSame(vserver, step.getVServer());
+
+        when(aaicq.getVserver()).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getVServer())
+                        .withMessageContaining("missing vserver in A&AI response");
+    }
+
+    @Test
+    public void testGetTargetEntity() {
+        when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(MY_TARGET);
+
+        assertEquals(MY_TARGET, step.getTargetEntity());
+
+        when(stepContext.getProperty(OperationProperties.AAI_TARGET_ENTITY)).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getTargetEntity())
+                        .withMessageContaining("missing A&AI target entity");
     }
 
     @Test
@@ -301,6 +357,10 @@ public class Step2Test {
         step.setProperties();
         verify(policyOperation).setProperty(OperationProperties.AAI_VNF, data);
 
+        when(aaicq.getGenericVnfByVfModuleModelInvariantId("my-model-invariant")).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getVnf())
+                        .withMessageContaining("missing generic VNF in A&AI response for my-model-invariant");
+
         // missing model invariant ID
         params.getTargetEntityIds().put(Step2.TARGET_MODEL_INVARIANT_ID, null);
         assertThatIllegalArgumentException().isThrownBy(() -> step.setProperties())
@@ -327,6 +387,14 @@ public class Step2Test {
 
         step.setProperties();
         verify(policyOperation).setProperty(OperationProperties.AAI_VNF_MODEL, data);
+
+        when(aaicq.getModelVerByVersionId("my-vnf-model-version-id")).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getVnfModel())
+                        .withMessageContaining("missing model version for generic VNF in A&AI response");
+
+        vnf.setModelVersionId(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getVnfModel())
+                        .withMessageContaining("missing model version ID for generic VNF in A&AI response");
     }
 
     @Test
@@ -452,6 +520,10 @@ public class Step2Test {
 
         step.setProperties();
         verify(policyOperation).setProperty(UsecasesConstants.AAI_DEFAULT_GENERIC_VNF, data);
+
+        when(aaicq.getDefaultGenericVnf()).thenReturn(null);
+        assertThatIllegalArgumentException().isThrownBy(() -> step.getDefaultGenericVnf())
+                        .withMessageContaining("missing generic VNF in A&AI response");
     }
 
     @Test