Multiplied connection to AAI and subscription to VNFM (if they fail) 27/101727/5
authorPiotr Borelowski <p.borelowski@partner.samsung.com>
Fri, 14 Feb 2020 08:15:38 +0000 (09:15 +0100)
committerPiotr Borelowski <p.borelowski@partner.samsung.com>
Mon, 24 Feb 2020 08:18:38 +0000 (08:18 +0000)
(+small changes required by OOM)

Ve-Vnfm (SOL002) Adapter project

Issue-ID: SO-2574
Signed-off-by: Piotr Borelowski <p.borelowski@partner.samsung.com>
Change-Id: I42bb30b4bbf256340123d64d203f461ed336ebc3

15 files changed:
adapters/mso-ve-vnfm-adapter/pom.xml
adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/aai/AaiConnection.java
adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/configuration/StartupConfiguration.java
adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/controller/NotificationController.java
adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/exception/VeVnfmException.java
adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/provider/AuthorizationHeadersProvider.java
adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/service/StartupService.java
adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/service/SubscribeSender.java [moved from adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/subscription/SubscribeSender.java with 60% similarity]
adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/service/SubscriberService.java
adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/service/SubscriptionScheduler.java [new file with mode: 0644]
adapters/mso-ve-vnfm-adapter/src/main/resources/application.yaml
adapters/mso-ve-vnfm-adapter/src/test/java/org/onap/so/adapters/vevnfm/controller/NotificationControllerTest.java
adapters/mso-ve-vnfm-adapter/src/test/java/org/onap/so/adapters/vevnfm/provider/AuthorizationHeadersProviderTest.java
adapters/mso-ve-vnfm-adapter/src/test/java/org/onap/so/adapters/vevnfm/service/StartupServiceTest.java
adapters/mso-ve-vnfm-adapter/src/test/java/org/onap/so/adapters/vevnfm/service/SubscribeSenderTest.java [moved from adapters/mso-ve-vnfm-adapter/src/test/java/org/onap/so/adapters/vevnfm/subscription/SubscribeSenderTest.java with 85% similarity]

index 4472956..d58f183 100644 (file)
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.springframework.retry</groupId>
+      <artifactId>spring-retry</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.onap.so.adapters</groupId>
       <artifactId>mso-vnfm-adapter-ext-clients</artifactId>
       <groupId>org.glassfish.jersey.inject</groupId>
       <artifactId>jersey-hk2</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-test</artifactId>
index 188b671..a2bd603 100644 (file)
@@ -22,11 +22,14 @@ package org.onap.so.adapters.vevnfm.aai;
 
 import java.util.List;
 import java.util.Optional;
+import org.apache.logging.log4j.util.Strings;
 import org.onap.aai.domain.yang.EsrSystemInfo;
 import org.onap.aai.domain.yang.EsrVnfm;
 import org.onap.aai.domain.yang.EsrVnfmList;
+import org.onap.so.adapters.vevnfm.exception.VeVnfmException;
 import org.onap.so.client.aai.AAIObjectType;
 import org.onap.so.client.aai.AAIResourcesClient;
+import org.onap.so.client.aai.entities.uri.AAIResourceUri;
 import org.onap.so.client.aai.entities.uri.AAIUriFactory;
 import org.onap.so.client.graphinventory.entities.uri.Depth;
 import org.slf4j.Logger;
@@ -40,10 +43,30 @@ public class AaiConnection {
 
     private static final int FIRST_INDEX = 0;
 
-    public EsrSystemInfo receiveVnfm() {
+    private static void isValid(final EsrSystemInfo info) throws VeVnfmException {
+        if (info == null || Strings.isBlank(info.getServiceUrl())) {
+            throw new VeVnfmException("No 'url' field in VNFM info");
+        }
+    }
+
+    public EsrSystemInfo receiveVnfm() throws VeVnfmException {
+        EsrSystemInfo info;
+
+        try {
+            info = receiveVnfmInternal();
+        } catch (Exception e) {
+            throw new VeVnfmException(e);
+        }
+
+        isValid(info);
+
+        return info;
+    }
+
+    private EsrSystemInfo receiveVnfmInternal() {
         final AAIResourcesClient resourcesClient = new AAIResourcesClient();
-        final Optional<EsrVnfmList> response =
-                resourcesClient.get(EsrVnfmList.class, AAIUriFactory.createResourceUri(AAIObjectType.VNFM_LIST));
+        final AAIResourceUri resourceUri = AAIUriFactory.createResourceUri(AAIObjectType.VNFM_LIST);
+        final Optional<EsrVnfmList> response = resourcesClient.get(EsrVnfmList.class, resourceUri);
 
         if (response.isPresent()) {
             final EsrVnfmList esrVnfmList = response.get();
index f7b7283..ae330f7 100644 (file)
@@ -20,7 +20,9 @@
 
 package org.onap.so.adapters.vevnfm.configuration;
 
+import org.onap.aai.domain.yang.EsrSystemInfo;
 import org.onap.so.adapters.vevnfm.service.StartupService;
+import org.onap.so.adapters.vevnfm.service.SubscriptionScheduler;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.context.event.ApplicationReadyEvent;
 import org.springframework.context.annotation.Configuration;
@@ -39,10 +41,14 @@ public class StartupConfiguration {
     @Autowired
     private StartupService startupService;
 
+    @Autowired
+    private SubscriptionScheduler subscriptionScheduler;
+
     @EventListener(ApplicationReadyEvent.class)
     public void onApplicationReadyEvent() throws Exception {
         if (!environment.acceptsProfiles(Profiles.of(TEST_PROFILE))) {
-            startupService.run();
+            final EsrSystemInfo info = startupService.receiveVnfm();
+            subscriptionScheduler.setInfo(info);
         }
     }
 }
index 1882b4e..cb324c3 100644 (file)
@@ -38,7 +38,7 @@ public class NotificationController {
     @Autowired
     private DmaapService dmaapService;
 
-    @PostMapping("${notification.url}")
+    @PostMapping("${vnfm.notification}")
     public ResponseEntity receiveNotification(@RequestBody final VnfLcmOperationOccurrenceNotification notification) {
         logger.info("Notification received {}", notification);
         dmaapService.send(notification);
index abd9ff9..a0c1c1e 100644 (file)
@@ -25,4 +25,8 @@ public class VeVnfmException extends Exception {
     public VeVnfmException(final String message) {
         super(message);
     }
+
+    public VeVnfmException(final Throwable cause) {
+        super(cause);
+    }
 }
index 251e0c4..838a67d 100644 (file)
 
 package org.onap.so.adapters.vevnfm.provider;
 
+import org.apache.logging.log4j.util.Strings;
 import org.onap.so.configuration.rest.BasicHttpHeadersProvider;
 
 public class AuthorizationHeadersProvider extends BasicHttpHeadersProvider {
 
     public void addAuthorization(final String authorization) {
+        if (Strings.isBlank(authorization)) {
+            return;
+        }
+
         getHttpHeaders().set(AUTHORIZATION_HEADER, authorization);
     }
 
index dfbafa2..3d21514 100644 (file)
 
 package org.onap.so.adapters.vevnfm.service;
 
-import org.apache.logging.log4j.util.Strings;
 import org.onap.aai.domain.yang.EsrSystemInfo;
 import org.onap.so.adapters.vevnfm.aai.AaiConnection;
 import org.onap.so.adapters.vevnfm.exception.VeVnfmException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.EnableRetry;
+import org.springframework.retry.annotation.Recover;
+import org.springframework.retry.annotation.Retryable;
 import org.springframework.stereotype.Service;
 
 @Service
+@EnableRetry
 public class StartupService {
 
-    @Autowired
-    private AaiConnection aaiConnection;
+    private static final Logger logger = LoggerFactory.getLogger(StartupService.class);
+
+    @Value("${vnfm.default-endpoint}")
+    private String vnfmDefaultEndpoint;
 
     @Autowired
-    private SubscriberService subscriberService;
+    private AaiConnection aaiConnection;
 
-    private static void isValid(final EsrSystemInfo info) throws VeVnfmException {
-        if (Strings.isBlank(info.getServiceUrl())) {
-            throw new VeVnfmException("No 'url' field in VNFM info");
-        }
+    @Retryable(value = {VeVnfmException.class}, maxAttempts = 5, backoff = @Backoff(delay = 5000, multiplier = 10))
+    public EsrSystemInfo receiveVnfm() throws VeVnfmException {
+        return aaiConnection.receiveVnfm();
     }
 
-    public void run() throws Exception {
-        final EsrSystemInfo info = aaiConnection.receiveVnfm();
-        isValid(info);
-        final boolean done = subscriberService.subscribe(info);
+    @Recover
+    public EsrSystemInfo recoverReceiveVnfm(final Throwable e) {
+        logger.warn("Connection to AAI failed");
+        final EsrSystemInfo info = new EsrSystemInfo();
+        info.setServiceUrl(vnfmDefaultEndpoint);
+        logger.warn("This EsrSystemInfo is used by default: {}", info);
 
-        if (!done) {
-            throw new VeVnfmException("Could not subscribe to VNFM");
-        }
+        return info;
     }
 }
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.so.adapters.vevnfm.subscription;
+package org.onap.so.adapters.vevnfm.service;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.so.adapters.vevnfm.exception.VeVnfmException;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.LccnSubscriptionRequest;
 import org.onap.so.rest.service.HttpRestServiceProvider;
 import org.slf4j.Logger;
@@ -29,11 +31,14 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+import lombok.ToString;
 
-@Component
+@Service
 public class SubscribeSender {
 
+    public static final String SLASH = "/";
+
     private static final Logger logger = LoggerFactory.getLogger(SubscribeSender.class);
 
     @Value("${vnfm.subscription}")
@@ -42,18 +47,37 @@ public class SubscribeSender {
     @Autowired
     private HttpRestServiceProvider restProvider;
 
-    public boolean send(final EsrSystemInfo info, final LccnSubscriptionRequest request) {
-        final ResponseEntity<String> response = restProvider.postHttpRequest(request, getUrl(info), String.class);
+    public String send(final EsrSystemInfo info, final LccnSubscriptionRequest request) throws VeVnfmException {
+        final ResponseEntity<SubscribeToManoResponse> response =
+                restProvider.postHttpRequest(request, getUrl(info), SubscribeToManoResponse.class);
 
         final HttpStatus statusCode = response.getStatusCode();
-        final String body = response.getBody();
+        final SubscribeToManoResponse body = response.getBody();
 
         logger.info("The VNFM replied with the code {} and the body {}", statusCode, body);
 
-        return HttpStatus.CREATED == statusCode;
+        if (HttpStatus.CREATED != statusCode) {
+            throw new VeVnfmException("The status code was different than " + HttpStatus.CREATED);
+        }
+
+        return body.id;
+    }
+
+    public boolean check(final EsrSystemInfo info, final String id) {
+        final ResponseEntity<SubscribeToManoResponse> response =
+                restProvider.getHttpResponse(getUrl(info) + SLASH + id, SubscribeToManoResponse.class);
+        return response.getBody() != null && response.getBody().id.equals(id);
     }
 
     private String getUrl(final EsrSystemInfo info) {
         return info.getServiceUrl() + vnfmSubscription;
     }
+
+    @ToString
+    static class SubscribeToManoResponse {
+        @JsonProperty("id")
+        String id;
+        @JsonProperty("callbackUri")
+        String callbackUri;
+    }
 }
index eefd9ba..9760584 100644 (file)
@@ -22,9 +22,10 @@ package org.onap.so.adapters.vevnfm.service;
 
 import com.squareup.okhttp.Credentials;
 import java.util.Collections;
+import org.apache.logging.log4j.util.Strings;
 import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.so.adapters.vevnfm.exception.VeVnfmException;
 import org.onap.so.adapters.vevnfm.provider.AuthorizationHeadersProvider;
-import org.onap.so.adapters.vevnfm.subscription.SubscribeSender;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.LccnSubscriptionRequest;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.SubscriptionsAuthentication;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.SubscriptionsAuthenticationParamsBasic;
@@ -35,16 +36,11 @@ import org.springframework.stereotype.Service;
 @Service
 public class SubscriberService {
 
-    private static final char COLON = ':';
+    @Value("${vevnfmadapter.endpoint}")
+    private String endpoint;
 
-    @Value("${system.url}")
-    private String systemUrl;
-
-    @Value("${server.port}")
-    private String serverPort;
-
-    @Value("${notification.url}")
-    private String notificationUrl;
+    @Value("${vnfm.notification}")
+    private String notification;
 
     @Value("${spring.security.usercredentials[0].username}")
     private String username;
@@ -59,19 +55,40 @@ public class SubscriberService {
     private SubscribeSender sender;
 
     private static String getAuthorization(final EsrSystemInfo info) {
-        return Credentials.basic(info.getUserName(), info.getPassword());
+        if (info == null) {
+            return null;
+        }
+
+        final String userName = info.getUserName();
+
+        if (Strings.isBlank(userName)) {
+            return null;
+        }
+
+        final String password = info.getPassword();
+        return Credentials.basic(userName, password);
     }
 
-    public boolean subscribe(final EsrSystemInfo info) {
+    public String subscribe(final EsrSystemInfo info) throws VeVnfmException {
         try {
             headersProvider.addAuthorization(getAuthorization(info));
             final LccnSubscriptionRequest request = createRequest();
             return sender.send(info, request);
+        } catch (Exception e) {
+            throw new VeVnfmException(e);
         } finally {
             headersProvider.removeAuthorization();
         }
     }
 
+    public boolean checkSubscription(final EsrSystemInfo info, final String id) throws VeVnfmException {
+        try {
+            return sender.check(info, id);
+        } catch (Exception e) {
+            throw new VeVnfmException(e);
+        }
+    }
+
     private LccnSubscriptionRequest createRequest() {
         final LccnSubscriptionRequest request = new LccnSubscriptionRequest();
         request.callbackUri(getCallbackUri());
@@ -87,6 +104,6 @@ public class SubscriberService {
     }
 
     private String getCallbackUri() {
-        return systemUrl + COLON + serverPort + notificationUrl;
+        return endpoint + notification;
     }
 }
diff --git a/adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/service/SubscriptionScheduler.java b/adapters/mso-ve-vnfm-adapter/src/main/java/org/onap/so/adapters/vevnfm/service/SubscriptionScheduler.java
new file mode 100644 (file)
index 0000000..1642743
--- /dev/null
@@ -0,0 +1,71 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SO
+ * ================================================================================
+ * Copyright (C) 2020 Samsung. 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.
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.adapters.vevnfm.service;
+
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.so.adapters.vevnfm.exception.VeVnfmException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+@Service
+@EnableScheduling
+public class SubscriptionScheduler {
+
+    private static final Logger logger = LoggerFactory.getLogger(SubscriptionScheduler.class);
+
+    @Autowired
+    private SubscriberService subscriberService;
+
+    private String subscribedId;
+
+    private EsrSystemInfo info;
+
+    public void setInfo(final EsrSystemInfo info) {
+        this.info = info;
+    }
+
+    @Scheduled(fixedRate = 5000, initialDelay = 2000)
+    void subscribeTask() throws VeVnfmException {
+        if (info != null) {
+            if (subscribedId == null) {
+                logger.info("Starting subscribe task");
+                subscribedId = subscriberService.subscribe(info);
+            }
+        }
+    }
+
+    @Scheduled(fixedRate = 20000)
+    void checkSubscribeTask() throws VeVnfmException {
+        if (info != null) {
+            if (subscribedId != null) {
+                logger.info("Checking subscription: {}", subscribedId);
+                if (!subscriberService.checkSubscription(info, subscribedId)) {
+                    logger.info("Subscription {} not available", subscribedId);
+                    subscribedId = null;
+                }
+            }
+        }
+    }
+}
index 35871c5..72198b8 100644 (file)
 # limitations under the License.
 
 server:
-  port: 8080
+  port: 9098
 
-system:
-  url: http://localhost
-
-notification:
-  url: /lcm/v1/vnf/instances/notifications
+vevnfmadapter:
+  endpoint: http://so-ve-vnfm-adapter.onap:9098
 
 mso:
   key: 07a7159d3bf51a0e53be7a8f89699be7
@@ -31,10 +28,12 @@ aai:
   auth: 75C4483F9C05E2C33A8602635FA532397EC44AB667A2B64DED4FEE08DD932F2E3C1FEE
 
 vnfm:
+  default-endpoint: https://so-vnfm-simulator.onap:9093
   subscription: /vnflcm/v1/subscriptions
+  notification: /lcm/v1/vnf/instances/notifications
 
 dmaap:
-  endpoint: http://message-router:30227
+  endpoint: http://message-router.onap:30227
   topic: /events/unauthenticated.DCAE_CL_OUTPUT
 
 spring:
index 57638a1..974e6ec 100644 (file)
@@ -53,8 +53,8 @@ public class NotificationControllerTest {
     private static final String MINIMAL_JSON_CONTENT = "{}";
     private static final int ZERO = 0;
 
-    @Value("${notification.url}")
-    private String notificationUrl;
+    @Value("${vnfm.notification}")
+    private String notification;
 
     @Autowired
     private WebApplicationContext webApplicationContext;
@@ -74,7 +74,7 @@ public class NotificationControllerTest {
     @Test
     public void testReceiveNotification() throws Exception {
         // given
-        final MockHttpServletRequestBuilder request = MockMvcRequestBuilders.post(notificationUrl)
+        final MockHttpServletRequestBuilder request = MockMvcRequestBuilders.post(notification)
                 .contentType(MediaType.APPLICATION_JSON).content(MINIMAL_JSON_CONTENT);
 
         mockRestServer.expect(once(), anything()).andRespond(withSuccess());
index 64503dd..f9ae427 100644 (file)
@@ -28,6 +28,8 @@ import org.springframework.http.HttpHeaders;
 public class AuthorizationHeadersProviderTest {
 
     private static final String AUTHORIZATION_EXAMPLE = "authorization";
+    private static final String BLANK_EXAMPLE = "\t\n";
+    private static final String EMPTY = "";
 
     private final AuthorizationHeadersProvider provider = new AuthorizationHeadersProvider();
 
@@ -44,4 +46,41 @@ public class AuthorizationHeadersProviderTest {
         assertEquals(size, headers.size());
         assertFalse(headers.containsKey(AUTHORIZATION_HEADER));
     }
+
+    @Test
+    public void testBlankAuthorization() {
+        final HttpHeaders headers = provider.getHttpHeaders();
+        final int size = headers.size();
+
+        provider.addAuthorization(BLANK_EXAMPLE);
+        assertEquals(size, headers.size());
+    }
+
+    @Test
+    public void testEmptyAuthorization() {
+        final HttpHeaders headers = provider.getHttpHeaders();
+        final int size = headers.size();
+
+        provider.addAuthorization(EMPTY);
+        assertEquals(size, headers.size());
+    }
+
+    @Test
+    public void testNullAuthorization() {
+        final HttpHeaders headers = provider.getHttpHeaders();
+        final int size = headers.size();
+
+        provider.addAuthorization(null);
+        assertEquals(size, headers.size());
+    }
+
+    @Test
+    public void testRemoveAuthorization() {
+        final HttpHeaders headers = provider.getHttpHeaders();
+        final int size = headers.size();
+
+        provider.removeAuthorization();
+        provider.removeAuthorization();
+        assertEquals(size, headers.size());
+    }
 }
index 0f9c23e..d1d34a7 100644 (file)
@@ -20,7 +20,9 @@
 
 package org.onap.so.adapters.vevnfm.service;
 
-import static org.mockito.Mockito.*;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -30,62 +32,34 @@ import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.onap.aai.domain.yang.EsrSystemInfo;
 import org.onap.so.adapters.vevnfm.aai.AaiConnection;
-import org.onap.so.adapters.vevnfm.exception.VeVnfmException;
 
 @RunWith(MockitoJUnitRunner.class)
 public class StartupServiceTest {
 
-    @Mock
-    private AaiConnection aaiConnection;
+    private static final String URL = "rt";
+
+    @Rule
+    public ExpectedException thrown = ExpectedException.none();
 
     @Mock
-    private SubscriberService subscriberService;
+    private AaiConnection aaiConnection;
 
     @InjectMocks
     private StartupService startupService;
 
-    @Rule
-    public ExpectedException thrown = ExpectedException.none();
-
     @Test
     public void testSuccess() throws Exception {
         // given
         final EsrSystemInfo info = new EsrSystemInfo();
-        info.setServiceUrl("lh");
-        when(aaiConnection.receiveVnfm()).thenReturn(info);
-        when(subscriberService.subscribe(info)).thenReturn(true);
-
-        // when
-        startupService.run();
-
-        // then
-        verify(aaiConnection, times(1)).receiveVnfm();
-        verify(subscriberService, times(1)).subscribe(info);
-    }
+        info.setServiceUrl(URL);
 
-    @Test
-    public void testFailureAai() throws Exception {
-        // given
-        final EsrSystemInfo info = new EsrSystemInfo();
         when(aaiConnection.receiveVnfm()).thenReturn(info);
 
-        thrown.expect(VeVnfmException.class);
-
         // when
-        startupService.run();
-    }
-
-    @Test
-    public void testFailureSubscriber() throws Exception {
-        // given
-        final EsrSystemInfo info = new EsrSystemInfo();
-        info.setServiceUrl("lh");
-        when(aaiConnection.receiveVnfm()).thenReturn(info);
-        when(subscriberService.subscribe(info)).thenReturn(false);
+        final EsrSystemInfo systemInfo = startupService.receiveVnfm();
 
-        thrown.expect(VeVnfmException.class);
-
-        // when
-        startupService.run();
+        // then
+        verify(aaiConnection).receiveVnfm();
+        assertEquals(info, systemInfo);
     }
 }
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.so.adapters.vevnfm.subscription;
+package org.onap.so.adapters.vevnfm.service;
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.onap.so.adapters.vevnfm.service.SubscribeSender.SLASH;
 import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
 import static org.springframework.test.web.client.ExpectedCount.once;
 import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
@@ -33,6 +34,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.onap.aai.domain.yang.EsrSystemInfo;
 import org.onap.so.adapters.vevnfm.configuration.StartupConfiguration;
+import org.onap.so.adapters.vevnfm.exception.VeVnfmException;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.LccnSubscriptionRequest;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -50,8 +52,9 @@ import org.springframework.web.client.RestTemplate;
 @ActiveProfiles(StartupConfiguration.TEST_PROFILE)
 public class SubscribeSenderTest {
 
-    private static final String SLASH = "/";
-    private static final String MINIMAL_JSON_CONTENT = "{}";
+    private static final String URL = "lh";
+    private static final String ID = "1a2s3d4f";
+    private static final String JSON = "{\"id\":\"" + ID + "\"}";
 
     private static final Gson GSON;
 
@@ -78,22 +81,22 @@ public class SubscribeSenderTest {
     }
 
     @Test
-    public void testSuccess() {
+    public void testSuccess() throws VeVnfmException {
         // given
         final EsrSystemInfo info = new EsrSystemInfo();
-        info.setServiceUrl("lh");
+        info.setServiceUrl(URL);
         final LccnSubscriptionRequest request = new LccnSubscriptionRequest();
 
         mockRestServer.expect(once(), requestTo(SLASH + info.getServiceUrl() + vnfmSubscription))
                 .andExpect(header(CONTENT_TYPE, CoreMatchers.containsString(MediaType.APPLICATION_JSON_VALUE)))
                 .andExpect(method(HttpMethod.POST)).andExpect(content().json(GSON.toJson(request)))
-                .andRespond(withStatus(HttpStatus.CREATED).body(MINIMAL_JSON_CONTENT));
+                .andRespond(withStatus(HttpStatus.CREATED).body(JSON).contentType(MediaType.APPLICATION_JSON));
 
         // when
-        final boolean done = sender.send(info, request);
+        final String id = sender.send(info, request);
 
         // then
-        assertTrue(done);
         mockRestServer.verify();
+        assertEquals(ID, id);
     }
 }