Handling null source and target data in CloudEventData. 16/142816/8
authorSourabh Verma <sv001010507@techmahindra.com>
Mon, 5 Jan 2026 11:53:43 +0000 (17:23 +0530)
committerSourabh Verma <sv001010507@techmahindra.com>
Wed, 14 Jan 2026 08:06:13 +0000 (13:36 +0530)
-A delta report with null or empty source/target would generate a cloud event with null source and target data.

-The patch fixed the issue and the source and target data in cloud event are populated only when they are present in delta report.

Issue-ID: CPS-3105
Change-Id: Ic76004fdcf4e2f63cdf415f2fc7645203ba17258
Signed-off-by: Sourabh Verma <sv001010507@techmahindra.com>
cps-service/src/main/java/org/onap/cps/events/CpsDataUpdateEventsProducer.java
cps-service/src/main/java/org/onap/cps/utils/DataMapUtils.java
cps-service/src/test/groovy/org/onap/cps/utils/DataMapUtilsSpec.groovy

index 2e8dcb8..74a8b25 100644 (file)
 package org.onap.cps.events;
 
 import static org.onap.cps.events.model.EventPayload.Action.fromValue;
+import static org.onap.cps.utils.DataMapUtils.hasEntries;
 
 import io.cloudevents.CloudEvent;
 import io.micrometer.core.annotation.Timed;
+import java.io.Serializable;
 import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -133,8 +135,14 @@ public class CpsDataUpdateEventsProducer {
     private CpsDataUpdatedEvent toCpsDataUpdatedEvent(final Anchor anchor, final OffsetDateTime observedTimestamp,
                                                       final DeltaReport deltaReport) {
         final CloudEventData cloudEventData = new CloudEventData();
-        cloudEventData.setSourceData(jsonObjectMapper.asJsonString(deltaReport.getSourceData()));
-        cloudEventData.setTargetData(jsonObjectMapper.asJsonString(deltaReport.getTargetData()));
+        final Map<String, Serializable> sourceData = deltaReport.getSourceData();
+        final Map<String, Serializable> targetData = deltaReport.getTargetData();
+        if (hasEntries(sourceData)) {
+            cloudEventData.setSourceData(jsonObjectMapper.asJsonString(sourceData));
+        }
+        if (hasEntries(targetData)) {
+            cloudEventData.setTargetData(jsonObjectMapper.asJsonString(targetData));
+        }
         final EventPayload updateEventData = new EventPayload();
         updateEventData.setObservedTimestamp(DateTimeUtility.toString(observedTimestamp));
         updateEventData.setDataspaceName(anchor.getDataspaceName());
index fabae6d..b1cc2a5 100644 (file)
@@ -67,6 +67,10 @@ public class DataMapUtils {
                 .put("dataNodes", dataMaps).build();
     }
 
+    public static boolean hasEntries(final Map<?, ?> map) {
+        return map != null && !map.isEmpty();
+    }
+
     private static List<Map<String, Object>> toDataNodesWithIdentifier(final List<DataNode> dataNodeList,
                                                                        final String prefix) {
         final List<Map<String, Object>> dataMaps = new ArrayList<>(dataNodeList.size());
index 6ff41c1..1f6868c 100644 (file)
@@ -98,6 +98,20 @@ class DataMapUtilsSpec extends Specification {
             result.isEmpty()
     }
 
+    def 'Check if a map is populated with #scenario.'() {
+        given: 'a map'
+            Map testMap = inputMap
+        when: 'checking if the map is populated'
+            boolean result = DataMapUtils.hasEntries(testMap)
+        then: 'the result contains expected value'
+            result == expectedResult
+        where: 'the following maps are checked'
+            scenario            | inputMap          || expectedResult
+            'a null map'        | null              || false
+            'an empty map'      | [:]               || false
+            'a populated map'   | [key: 'value']    || true
+    }
+
     def dataNode = buildDataNode(
         "/parent",[parentLeaf:'parentLeafValue', parentLeafList:['parentLeafListEntry1','parentLeafListEntry2']],[
         buildDataNode('/parent/child-list[@id="1/2"]',[listElementLeaf:'listElement1leafValue'],noChildren),