From 79dc74fd69086cf9937ed06241fed9a2772b0fba Mon Sep 17 00:00:00 2001 From: sourabh_sourabh Date: Wed, 29 Jun 2022 12:36:40 +0100 Subject: [PATCH] Composite state transition code change - Code cannge to set datastore to Unsynchronized when state moves from advice to ready - if resource data is not available or there is any issue while reading data from simulator then state will be set to synchronized else remain unsynchronized. - Handle serialization failure on empty bean. Issue-ID: CPS-1000 Signed-off-by: sourabh_sourabh Change-Id: Ie51a787770da649e00aaefc00341756f92f9fa83 --- cps-application/src/main/resources/application.yml | 2 ++ .../ncmp/api/inventory/InventoryPersistence.java | 20 +++++------ .../ncmp/api/inventory/sync/DataSyncWatchdog.java | 15 ++++++--- .../api/inventory/sync/ModuleSyncWatchdog.java | 39 +++++++++++++++++----- .../org/onap/cps/utils/JsonObjectMapperSpec.groovy | 7 ++-- 5 files changed, 58 insertions(+), 25 deletions(-) diff --git a/cps-application/src/main/resources/application.yml b/cps-application/src/main/resources/application.yml index 14abebb2be..d16e977704 100644 --- a/cps-application/src/main/resources/application.yml +++ b/cps-application/src/main/resources/application.yml @@ -82,6 +82,8 @@ spring: jackson: default-property-inclusion: NON_NULL + serialization: + FAIL_ON_EMPTY_BEANS: false app: ncmp: async-m2m: diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java index f0d1c9b4b7..d47da6c0cf 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistence.java @@ -47,7 +47,9 @@ public class InventoryPersistence { private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; - private static final String XPATH_TO_CM_HANDLE = "/dmi-registry/cm-handles[@id='" + "%s" + "']"; + private String xpathCmHandle = "/dmi-registry/cm-handles[@id='" + "%s" + "']"; + + private static final String ANCESTOR_CM_HANDLES = "\"]/ancestor::cm-handles"; private final JsonObjectMapper jsonObjectMapper; @@ -57,8 +59,6 @@ public class InventoryPersistence { private final CpsDataPersistenceService cpsDataPersistenceService; - private static final CompositeStateBuilder compositeStateBuilder = new CompositeStateBuilder(); - /** * Get the Cm Handle Composite State from the data node. * @@ -67,9 +67,9 @@ public class InventoryPersistence { */ public CompositeState getCmHandleState(final String cmHandleId) { final DataNode stateAsDataNode = cpsDataService.getDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - String.format(XPATH_TO_CM_HANDLE, cmHandleId) + "/state", + String.format(xpathCmHandle, cmHandleId) + "/state", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); - return compositeStateBuilder.fromDataNode(stateAsDataNode).build(); + return new CompositeStateBuilder().fromDataNode(stateAsDataNode).build(); } /** @@ -82,7 +82,7 @@ public class InventoryPersistence { final String cmHandleJsonData = String.format("{\"state\":%s}", jsonObjectMapper.asJsonString(compositeState)); cpsDataService.replaceNodeTree(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - String.format(XPATH_TO_CM_HANDLE, cmHandleId), + String.format(xpathCmHandle, cmHandleId), cmHandleJsonData, OffsetDateTime.now()); } @@ -95,7 +95,7 @@ public class InventoryPersistence { public List getCmHandlesByState(final CmHandleState cmHandleState) { return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, "//state[@cm-handle-state=\"" - + cmHandleState + "\"]/ancestor::cm-handles", + + cmHandleState + ANCESTOR_CM_HANDLES, FetchDescendantsOption.OMIT_DESCENDANTS); } @@ -121,7 +121,7 @@ public class InventoryPersistence { public List getCmHandlesByIdAndState(final String cmHandleId, final CmHandleState cmHandleState) { return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, "//cm-handles[@id='" + cmHandleId + "']/state[@cm-handle-state=\"" - + cmHandleState + "\"]/ancestor::cm-handles", + + cmHandleState + ANCESTOR_CM_HANDLES, FetchDescendantsOption.OMIT_DESCENDANTS); } @@ -133,7 +133,7 @@ public class InventoryPersistence { public List getCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) { return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, "//state/datastores" - + "/operational[@sync-state=\"" + dataStoreSyncState + "\"]/ancestor::cm-handles", + + "/operational[@sync-state=\"" + dataStoreSyncState + ANCESTOR_CM_HANDLES, FetchDescendantsOption.OMIT_DESCENDANTS); } @@ -160,7 +160,7 @@ public class InventoryPersistence { private DataNode getCmHandleDataNode(final String cmHandle) { return cpsDataService.getDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, - String.format(XPATH_TO_CM_HANDLE, cmHandle), + String.format(xpathCmHandle, cmHandle), FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java index 153921a9f7..adfa33ad81 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdog.java @@ -21,6 +21,7 @@ package org.onap.cps.ncmp.api.inventory.sync; import java.time.OffsetDateTime; +import java.util.function.Consumer; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsDataService; @@ -60,15 +61,21 @@ public class DataSyncWatchdog { } else { cpsDataService.saveData("NFP-Operational", cmHandleId, resourceData, OffsetDateTime.now()); + setSyncStateToSynchronized().accept(compositeState); + inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); } + unSynchronizedReadyCmHandle = syncUtils.getAnUnSynchronizedReadyCmHandle(); + } + log.debug("No Cm-Handles currently found in an READY State and Operational Sync State is UNSYNCHRONIZED"); + } + + private Consumer setSyncStateToSynchronized() { + return compositeState -> { compositeState.setLastUpdateTimeNow(); compositeState.getDataStores() .setOperationalDataStore(CompositeState.Operational.builder() .dataStoreSyncState(DataStoreSyncState.SYNCHRONIZED) .lastSyncTime(CompositeState.nowInSyncTimeFormat()).build()); - inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); - unSynchronizedReadyCmHandle = syncUtils.getAnUnSynchronizedReadyCmHandle(); - } - log.debug("No Cm-Handles currently found in an READY State and Operational Sync State is UNSYNCHRONIZED"); + }; } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java index 402f9f6b4f..ac53d881c1 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdog.java @@ -22,11 +22,13 @@ package org.onap.cps.ncmp.api.inventory.sync; import java.util.List; +import java.util.function.Consumer; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.inventory.CmHandleState; import org.onap.cps.ncmp.api.inventory.CompositeState; +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState; import org.onap.cps.ncmp.api.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.inventory.LockReasonCategory; import org.springframework.scheduling.annotation.Scheduled; @@ -54,17 +56,14 @@ public class ModuleSyncWatchdog { final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId); try { moduleSyncService.syncAndCreateSchemaSetAndAnchor(advisedCmHandle); - compositeState.setCmHandleState(CmHandleState.READY); + setCompositeStateToReadyWithInitialDataStoreSyncState().accept(compositeState); } catch (final Exception e) { - compositeState.setCmHandleState(CmHandleState.LOCKED); + setCompositeStateToLocked().accept(compositeState); syncUtils.updateLockReasonDetailsAndAttempts(compositeState, - LockReasonCategory.LOCKED_MISBEHAVING, - e.getMessage()); + LockReasonCategory.LOCKED_MISBEHAVING, e.getMessage()); } - compositeState.setLastUpdateTimeNow(); inventoryPersistence.saveCmHandleState(cmHandleId, compositeState); - log.info("{} is now in {} state", cmHandleId, - advisedCmHandle.getCompositeState().getCmHandleState()); + log.debug("{} is now in {} state", cmHandleId, compositeState.getCmHandleState().name()); advisedCmHandle = syncUtils.getAnAdvisedCmHandle(); } log.debug("No Cm-Handles currently found in an ADVISED state"); @@ -87,11 +86,33 @@ public class ModuleSyncWatchdog { } } + private Consumer setCompositeStateToLocked() { + return compositeState -> { + compositeState.setCmHandleState(CmHandleState.LOCKED); + compositeState.setLastUpdateTimeNow(); + }; + } + + private Consumer setCompositeStateToReadyWithInitialDataStoreSyncState() { + return compositeState -> { + compositeState.setCmHandleState(CmHandleState.READY); + final CompositeState.Operational operational = CompositeState.Operational.builder() + .dataStoreSyncState(DataStoreSyncState.UNSYNCHRONIZED) + .lastSyncTime(CompositeState.nowInSyncTimeFormat()) + .build(); + final CompositeState.DataStores dataStores = CompositeState.DataStores.builder() + .operationalDataStore(operational) + .build(); + compositeState.setDataStores(dataStores); + }; + } + private void setCompositeStateToAdvisedAndRetainOldLockReasonDetails(final CompositeState compositeState) { compositeState.setCmHandleState(CmHandleState.ADVISED); compositeState.setLastUpdateTimeNow(); final String oldLockReasonDetails = compositeState.getLockReason().getDetails(); - compositeState.setLockReason(CompositeState.LockReason.builder() - .details(oldLockReasonDetails).build()); + final CompositeState.LockReason lockReason = CompositeState.LockReason.builder() + .details(oldLockReasonDetails).build(); + compositeState.setLockReason(lockReason); } } diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy index acb52413f8..461014418e 100644 --- a/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy @@ -22,6 +22,7 @@ package org.onap.cps.utils import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.SerializationFeature import groovy.json.JsonSlurper import org.onap.cps.TestUtils import org.onap.cps.spi.exceptions.DataValidationException @@ -79,10 +80,12 @@ class JsonObjectMapperSpec extends Specification { def 'Map a unstructured object to json String.'() { given: 'Unstructured object' def object = new Object() + and: 'disable serialization failure on empty bean' + spiedObjectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); when: 'the object is mapped to string' jsonObjectMapper.asJsonString(object); - then: 'an exception is thrown' - thrown(DataValidationException) + then: 'no exception is thrown' + noExceptionThrown() } def 'Map a structurally compatible json String to JsonNode.'() { -- 2.16.6