publishLcmEventBatchAsynchronously is not async 38/135038/4
authordanielhanrahan <daniel.hanrahan@est.tech>
Tue, 20 Jun 2023 17:19:59 +0000 (18:19 +0100)
committerdanielhanrahan <daniel.hanrahan@est.tech>
Wed, 21 Jun 2023 11:24:13 +0000 (12:24 +0100)
Spring @Async has a limitation where calling the async method from
within the same class won't work, as the method needs to be proxied,
and calling from the same class bypasses the proxy and calls the
underlying method directly, thus running synchronously.

Issue-ID: CPS-1749
Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech>
Change-Id: I7f198487dc18b359654dc38b5cf8fd600d33e189

cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy

index 18bdcbe..2ae1188 100644 (file)
@@ -23,7 +23,6 @@ package org.onap.cps.ncmp.api.impl.events.lcm;
 import java.util.Map;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.ncmp.api.inventory.CmHandleState;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
 
 /**
  * The implementation of it should handle the persisting of composite state and delegate the request to publish the
@@ -46,13 +45,4 @@ public interface LcmEventsCmHandleStateHandler {
      */
     void updateCmHandleStateBatch(final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle);
 
-    /**
-     * Publish LCM Event.
-     *
-     * @param targetNcmpServiceCmHandle  target NcmpServiceCmHandle
-     * @param currentNcmpServiceCmHandle current NcmpServiceCmHandle
-     */
-    void publishLcmEventAsynchronously(final NcmpServiceCmHandle targetNcmpServiceCmHandle,
-            final NcmpServiceCmHandle currentNcmpServiceCmHandle);
-
 }
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java
new file mode 100644 (file)
index 0000000..3742719
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.events.lcm;
+
+import java.util.Collection;
+import lombok.RequiredArgsConstructor;
+import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
+import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.events.lcm.v1.LcmEvent;
+import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class LcmEventsCmHandleStateHandlerAsyncHelper {
+
+    private final LcmEventsCreator lcmEventsCreator;
+    private final LcmEventsService lcmEventsService;
+
+    /**
+     * Publish LCM Event in asynchronous manner.
+     *
+     * @param targetNcmpServiceCmHandle  target NcmpServiceCmHandle
+     * @param currentNcmpServiceCmHandle current NcmpServiceCmHandle
+     */
+    @Async("notificationExecutor")
+    public void publishLcmEventAsynchronously(final NcmpServiceCmHandle targetNcmpServiceCmHandle,
+                                              final NcmpServiceCmHandle currentNcmpServiceCmHandle) {
+        publishLcmEvent(targetNcmpServiceCmHandle, currentNcmpServiceCmHandle);
+    }
+
+    /**
+     * Publish LcmEvent in batches and in asynchronous manner.
+     *
+     * @param cmHandleTransitionPairs Pair of existing and modified cm handle represented as YangModelCmHandle
+     */
+    @Async("notificationExecutor")
+    public void publishLcmEventBatchAsynchronously(
+            final Collection<LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair> cmHandleTransitionPairs) {
+        cmHandleTransitionPairs.forEach(cmHandleTransitionPair -> publishLcmEvent(
+                toNcmpServiceCmHandle(cmHandleTransitionPair.getTargetYangModelCmHandle()),
+                toNcmpServiceCmHandle(cmHandleTransitionPair.getCurrentYangModelCmHandle())));
+    }
+
+    private void publishLcmEvent(final NcmpServiceCmHandle targetNcmpServiceCmHandle,
+                                 final NcmpServiceCmHandle existingNcmpServiceCmHandle) {
+        final String cmHandleId = targetNcmpServiceCmHandle.getCmHandleId();
+        final LcmEventHeader lcmEventHeader =
+                lcmEventsCreator.populateLcmEventHeader(cmHandleId, targetNcmpServiceCmHandle,
+                        existingNcmpServiceCmHandle);
+        final LcmEvent lcmEvent =
+                lcmEventsCreator.populateLcmEvent(cmHandleId, targetNcmpServiceCmHandle, existingNcmpServiceCmHandle);
+        lcmEventsService.publishLcmEvent(cmHandleId, lcmEvent, lcmEventHeader);
+    }
+
+    private static NcmpServiceCmHandle toNcmpServiceCmHandle(final YangModelCmHandle yangModelCmHandle) {
+        return YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(yangModelCmHandle);
+    }
+}
index f42cd39..2f77ec3 100644 (file)
@@ -43,9 +43,6 @@ import org.onap.cps.ncmp.api.inventory.CompositeState;
 import org.onap.cps.ncmp.api.inventory.CompositeStateUtils;
 import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
-import org.onap.cps.ncmp.events.lcm.v1.LcmEvent;
-import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader;
-import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
 @Slf4j
@@ -54,8 +51,7 @@ import org.springframework.stereotype.Service;
 public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleStateHandler {
 
     private final InventoryPersistence inventoryPersistence;
-    private final LcmEventsCreator lcmEventsCreator;
-    private final LcmEventsService lcmEventsService;
+    private final LcmEventsCmHandleStateHandlerAsyncHelper lcmEventsCmHandleStateHandlerAsyncHelper;
 
     @Override
     public void updateCmHandleState(final YangModelCmHandle updatedYangModelCmHandle,
@@ -70,7 +66,8 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState
             final YangModelCmHandle currentYangModelCmHandle = YangModelCmHandle.deepCopyOf(updatedYangModelCmHandle);
             updateToSpecifiedCmHandleState(updatedYangModelCmHandle, targetCmHandleState);
             persistCmHandle(updatedYangModelCmHandle, currentYangModelCmHandle);
-            publishLcmEventAsynchronously(toNcmpServiceCmHandle(updatedYangModelCmHandle),
+            lcmEventsCmHandleStateHandlerAsyncHelper.publishLcmEventAsynchronously(
+                    toNcmpServiceCmHandle(updatedYangModelCmHandle),
                     toNcmpServiceCmHandle(currentYangModelCmHandle));
         }
     }
@@ -82,37 +79,7 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState
         final Collection<CmHandleTransitionPair> cmHandleTransitionPairs =
                 prepareCmHandleTransitionBatch(cmHandleStatePerCmHandle);
         persistCmHandleBatch(cmHandleTransitionPairs);
-        publishLcmEventBatchAsynchronously(cmHandleTransitionPairs);
-    }
-
-    @Async("notificationExecutor")
-    @Override
-    public void publishLcmEventAsynchronously(final NcmpServiceCmHandle targetNcmpServiceCmHandle,
-            final NcmpServiceCmHandle currentNcmpServiceCmHandle) {
-        publishLcmEvent(targetNcmpServiceCmHandle, currentNcmpServiceCmHandle);
-    }
-
-    /**
-     * Publish LcmEvent in batches and in asynchronous manner.
-     *
-     * @param cmHandleTransitionPairs Pair of existing and modified cm handle represented as YangModelCmHandle
-     */
-    @Async("notificationExecutor")
-    public void publishLcmEventBatchAsynchronously(final Collection<CmHandleTransitionPair> cmHandleTransitionPairs) {
-        cmHandleTransitionPairs.forEach(cmHandleTransitionPair -> publishLcmEvent(
-                toNcmpServiceCmHandle(cmHandleTransitionPair.getTargetYangModelCmHandle()),
-                toNcmpServiceCmHandle(cmHandleTransitionPair.getCurrentYangModelCmHandle())));
-    }
-
-    private void publishLcmEvent(final NcmpServiceCmHandle targetNcmpServiceCmHandle,
-            final NcmpServiceCmHandle existingNcmpServiceCmHandle) {
-        final String cmHandleId = targetNcmpServiceCmHandle.getCmHandleId();
-        final LcmEventHeader lcmEventHeader =
-                lcmEventsCreator.populateLcmEventHeader(cmHandleId, targetNcmpServiceCmHandle,
-                        existingNcmpServiceCmHandle);
-        final LcmEvent lcmEvent =
-                lcmEventsCreator.populateLcmEvent(cmHandleId, targetNcmpServiceCmHandle, existingNcmpServiceCmHandle);
-        lcmEventsService.publishLcmEvent(cmHandleId, lcmEvent, lcmEventHeader);
+        lcmEventsCmHandleStateHandlerAsyncHelper.publishLcmEventBatchAsynchronously(cmHandleTransitionPairs);
     }
 
     private Collection<CmHandleTransitionPair> prepareCmHandleTransitionBatch(
index e449d65..bfebc44 100644 (file)
@@ -39,7 +39,8 @@ class LcmEventsCmHandleStateHandlerImplSpec extends Specification {
     def mockLcmEventsCreator = Mock(LcmEventsCreator)
     def mockLcmEventsService = Mock(LcmEventsService)
 
-    def objectUnderTest = new LcmEventsCmHandleStateHandlerImpl(mockInventoryPersistence, mockLcmEventsCreator, mockLcmEventsService)
+    def lcmEventsCmHandleStateHandlerAsyncHelper = new LcmEventsCmHandleStateHandlerAsyncHelper(mockLcmEventsCreator, mockLcmEventsService)
+    def objectUnderTest = new LcmEventsCmHandleStateHandlerImpl(mockInventoryPersistence, lcmEventsCmHandleStateHandlerAsyncHelper)
 
     def cmHandleId = 'cmhandle-id-1'
     def compositeState