summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthieu Geerebaert <matthieu.geerebaert@orange.com>2019-03-04 16:04:21 +0000
committerGerrit Code Review <gerrit@onap.org>2019-03-04 16:04:21 +0000
commit54f4f123ca4fd37ded22dc7887a4bb7bb468f01b (patch)
tree79ad4c838dcc9432bad0c7688b514f9f9655153c /src
parente0e7ba60753556c5a135ebc057ad3780cddacb28 (diff)
parentd6df1fa47283fd52c8b1970d16c994919203f59e (diff)
Merge "Add DMaaP Integration to retrieve AAI-EVENT"
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java6
-rwxr-xr-xsrc/main/java/org/onap/nbi/apis/hub/HubResource.java118
-rw-r--r--src/main/java/org/onap/nbi/apis/hub/model/EventType.java70
-rw-r--r--src/main/java/org/onap/nbi/apis/hub/model/ServiceInstanceEvent.java90
-rw-r--r--src/main/java/org/onap/nbi/apis/hub/service/CheckDMaaPEventsManager.java199
-rw-r--r--src/main/java/org/onap/nbi/apis/hub/service/DMaaPEventsScheduler.java40
-rw-r--r--src/main/java/org/onap/nbi/apis/hub/service/EventFactory.java98
-rwxr-xr-xsrc/main/java/org/onap/nbi/apis/hub/service/NotifierService.java35
-rw-r--r--src/main/java/org/onap/nbi/configuration/AppContext.java31
-rw-r--r--src/main/resources/application-test.properties7
-rw-r--r--src/main/resources/application.properties9
-rw-r--r--src/test/java/org/onap/nbi/api/listener/ListenerResource.java140
-rw-r--r--src/test/resources/karatetest/features/03--Subscriber.feature94
-rw-r--r--src/test/resources/mappings/dmaap_get_aaievents.json16
14 files changed, 749 insertions, 204 deletions
diff --git a/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java b/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java
index 9060249..80563d5 100644
--- a/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java
+++ b/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java
@@ -50,4 +50,8 @@ public final class OnapComponentsUrlPaths {
public static final String MSO_CREATE_E2ESERVICE_INSTANCE_PATH = "/onap/so/infra/e2eServiceInstances/v3";
public static final String MSO_DELETE_E2ESERVICE_INSTANCE_PATH = "/onap/so/infra/e2eServiceInstances/v3/";
public static final String MSO_GET_E2EREQUEST_STATUS_PATH = "/onap/so/infra/e2eServiceInstances/v3/$serviceId/operations/$operationId";
-}
+
+ // DMaaP Message Router REST Client
+ public static final String DMAAP_CONSUME_EVENTS =
+ "/events/$topic/$consumergroup/$consumerid?timeout=$timeout";
+} \ No newline at end of file
diff --git a/src/main/java/org/onap/nbi/apis/hub/HubResource.java b/src/main/java/org/onap/nbi/apis/hub/HubResource.java
index 0f94802..ac073c1 100755
--- a/src/main/java/org/onap/nbi/apis/hub/HubResource.java
+++ b/src/main/java/org/onap/nbi/apis/hub/HubResource.java
@@ -1,23 +1,24 @@
/**
* Copyright (c) 2018 Orange
*
- * 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
+ * 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.
+ * 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.
*/
package org.onap.nbi.apis.hub;
-import java.net.URI;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.onap.nbi.apis.hub.model.Subscriber;
import org.onap.nbi.apis.hub.model.Subscription;
+import org.onap.nbi.apis.hub.service.CheckDMaaPEventsManager;
import org.onap.nbi.apis.hub.service.SubscriptionService;
import org.onap.nbi.commons.JsonRepresentation;
import org.onap.nbi.commons.MultiCriteriaRequestBuilder;
@@ -42,67 +43,80 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
@RestController
@RequestMapping("/hub")
@EnableScheduling
public class HubResource extends ResourceManagement {
- Logger logger = LoggerFactory.getLogger(HubResource.class);
+ Logger logger = LoggerFactory.getLogger(HubResource.class);
- @Autowired
- MongoTemplate mongoTemplate;
+ @Autowired
+ MongoTemplate mongoTemplate;
- @Autowired
- SubscriptionService subscriptionService;
+ @Autowired
+ SubscriptionService subscriptionService;
- @Autowired
- MultiCriteriaRequestBuilder multiCriteriaRequestBuilder;
+ @Autowired
+ MultiCriteriaRequestBuilder multiCriteriaRequestBuilder;
- @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity<Object> createEventSubscription(@RequestBody Subscription subscription,
- @RequestParam MultiValueMap<String, String> params) {
- logger.debug("POST request for subscription : {}", subscription);
- Subscriber subscriber = subscriptionService.createSubscription(subscription);
- JsonRepresentation filter = new JsonRepresentation(params);
- return this.createResponse(Subscription.createFromSubscriber(subscriber), filter);
-
- }
-
- @GetMapping(value = "/{subscriptionId}", produces = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity<Subscription> getSubscription(@PathVariable String subscriptionId) {
+ @Autowired
+ CheckDMaaPEventsManager checkDMaaPEventMAnager;
+ @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity<Object> createEventSubscription(@RequestBody Subscription subscription,
+ @RequestParam MultiValueMap<String, String> params) {
+ logger.debug("POST request for subscription : {}", subscription);
+ Subscriber subscriber = subscriptionService.createSubscription(subscription);
+ JsonRepresentation filter = new JsonRepresentation(params);
+ return this.createResponse(Subscription.createFromSubscriber(subscriber), filter);
- Optional<Subscriber> optionalSubscriber = subscriptionService.findSubscriptionById(subscriptionId);
- if (!optionalSubscriber.isPresent()) {
- return ResponseEntity.notFound().build();
- }
- return ResponseEntity.ok(Subscription.createFromSubscriber(optionalSubscriber.get()));
- }
-
- @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity<Object> findSubscribers(@RequestParam MultiValueMap<String, String> params) {
+ }
- Query query = multiCriteriaRequestBuilder.buildRequest(params);
- List<Subscriber> subscribers = mongoTemplate.find(query, Subscriber.class);
- JsonRepresentation filter = new JsonRepresentation(params);
- long totalCount = subscriptionService.countSubscription();
- HttpHeaders headers = new HttpHeaders();
- headers.add("X-Total-Count", String.valueOf(totalCount));
- headers.add("X-Result-Count", String.valueOf(subscribers.size()));
- List<Subscription> subscriptions = subscribers.stream()
- .map(Subscription::createFromSubscriber)
- .collect(Collectors.toList());
+ @GetMapping(value = "/{subscriptionId}", produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity<Subscription> getSubscription(@PathVariable String subscriptionId) {
- return this.findResponse(subscriptions, filter, headers);
+ Optional<Subscriber> optionalSubscriber =
+ subscriptionService.findSubscriptionById(subscriptionId);
+ if (!optionalSubscriber.isPresent()) {
+ return ResponseEntity.notFound().build();
}
+ return ResponseEntity.ok(Subscription.createFromSubscriber(optionalSubscriber.get()));
+ }
+
+ @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity<Object> findSubscribers(
+ @RequestParam MultiValueMap<String, String> params) {
+
+ Query query = multiCriteriaRequestBuilder.buildRequest(params);
+ List<Subscriber> subscribers = mongoTemplate.find(query, Subscriber.class);
+ JsonRepresentation filter = new JsonRepresentation(params);
+ long totalCount = subscriptionService.countSubscription();
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("X-Total-Count", String.valueOf(totalCount));
+ headers.add("X-Result-Count", String.valueOf(subscribers.size()));
+ List<Subscription> subscriptions =
+ subscribers.stream().map(Subscription::createFromSubscriber).collect(Collectors.toList());
+
+ return this.findResponse(subscriptions, filter, headers);
+
+ }
+
+ /*
+ * Resource to test for DMaaP Integration for subscribing to AAI-EVENTs
+ */
+ @GetMapping("/testaaievents")
+ @ResponseStatus(HttpStatus.OK)
+ public void testAAIEventListener() {
+ checkDMaaPEventMAnager.checkForDMaaPAAIEvents();
+ }
+
+ @DeleteMapping("/{subscriptionId}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deleteSubscription(@PathVariable String subscriptionId) {
+ logger.debug("DELETE request for subscription id #{}", subscriptionId);
+ subscriptionService.deleteSubscription(subscriptionId);
+ }
- @DeleteMapping("/{subscriptionId}")
- @ResponseStatus(HttpStatus.NO_CONTENT)
- public void deleteSubscription(@PathVariable String subscriptionId) {
- logger.debug("DELETE request for subscription id #{}", subscriptionId);
- subscriptionService.deleteSubscription(subscriptionId);
- }
}
diff --git a/src/main/java/org/onap/nbi/apis/hub/model/EventType.java b/src/main/java/org/onap/nbi/apis/hub/model/EventType.java
index 1702347..b4e1f1a 100644
--- a/src/main/java/org/onap/nbi/apis/hub/model/EventType.java
+++ b/src/main/java/org/onap/nbi/apis/hub/model/EventType.java
@@ -1,17 +1,15 @@
/**
- * Copyright (c) 2018 Orange
+ * Copyright (c) 2018 Orange
*
- * 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
+ * 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
+ * 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.
+ * 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.
*/
package org.onap.nbi.apis.hub.model;
@@ -20,36 +18,42 @@ import com.fasterxml.jackson.annotation.JsonValue;
public enum EventType {
- SERVICE_ORDER_CREATION("ServiceOrderCreationNotification"),
+ SERVICE_ORDER_CREATION("ServiceOrderCreationNotification"),
- SERVICE_ORDER_STATE_CHANGE("ServiceOrderStateChangeNotification"),
+ SERVICE_ORDER_STATE_CHANGE("ServiceOrderStateChangeNotification"),
- SERVICE_ORDER_ITEM_STATE_CHANGE("ServiceOrderItemStateChangeNotification");
+ SERVICE_ORDER_ITEM_STATE_CHANGE("ServiceOrderItemStateChangeNotification"),
- private String value;
+ SERVICE_CREATION("ServiceCreationNotification"),
- EventType(String value) {
- this.value = value;
- }
+ SERVICE_ATTRIBUTE_VALUE_CHANGE("ServiceAttributeValueChangeNotification"),
- @Override
- public String toString() {
- return String.valueOf(value);
- }
+ SERVICE_REMOVE("ServiceRemoveNotification");
- @JsonCreator
- public static EventType fromValue(String text) {
- for (EventType b : EventType.values()) {
- if (String.valueOf(b.value).equals(text)) {
- return b;
- }
- }
- return null;
- }
+ private String value;
- @JsonValue
- public String value() {
- return this.value;
+ EventType(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ @JsonCreator
+ public static EventType fromValue(String text) {
+ for (EventType b : EventType.values()) {
+ if (String.valueOf(b.value).equals(text)) {
+ return b;
+ }
}
+ return null;
+ }
+
+ @JsonValue
+ public String value() {
+ return this.value;
+ }
}
diff --git a/src/main/java/org/onap/nbi/apis/hub/model/ServiceInstanceEvent.java b/src/main/java/org/onap/nbi/apis/hub/model/ServiceInstanceEvent.java
new file mode 100644
index 0000000..4bbafdc
--- /dev/null
+++ b/src/main/java/org/onap/nbi/apis/hub/model/ServiceInstanceEvent.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2019 Huawei
+ *
+ * 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.
+ */
+
+package org.onap.nbi.apis.hub.model;
+
+import org.onap.nbi.apis.serviceorder.model.RelatedParty;
+import org.springframework.data.annotation.Id;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ServiceInstanceEvent {
+
+ @Id
+ @JsonProperty("id")
+ private String id = null;
+
+ @JsonProperty("href")
+ private String href = null;
+
+ @JsonProperty("name")
+ private String name = null;
+
+ @JsonProperty("type")
+ private String type = "service-instance";
+
+ @JsonProperty("state")
+ private String state = null;
+
+ @JsonProperty("relatedParty")
+ private RelatedParty relatedParty = null;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getHref() {
+ return href;
+ }
+
+ public void setHref(String href) {
+ this.href = href;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public RelatedParty getRelatedParty() {
+ return relatedParty;
+ }
+
+ public void setRelatedParty(RelatedParty relatedParty) {
+ this.relatedParty = relatedParty;
+ }
+
+}
diff --git a/src/main/java/org/onap/nbi/apis/hub/service/CheckDMaaPEventsManager.java b/src/main/java/org/onap/nbi/apis/hub/service/CheckDMaaPEventsManager.java
new file mode 100644
index 0000000..6e2811f
--- /dev/null
+++ b/src/main/java/org/onap/nbi/apis/hub/service/CheckDMaaPEventsManager.java
@@ -0,0 +1,199 @@
+/**
+ * Copyright (c) 2019 Huawei
+ *
+ * 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.
+ */
+
+package org.onap.nbi.apis.hub.service;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import org.onap.nbi.OnapComponentsUrlPaths;
+import org.onap.nbi.apis.hub.model.Event;
+import org.onap.nbi.apis.hub.model.EventType;
+import org.onap.nbi.apis.hub.model.ServiceInstanceEvent;
+import org.onap.nbi.apis.hub.repository.SubscriberRepository;
+import org.onap.nbi.apis.serviceorder.model.RelatedParty;
+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.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+
+@Service
+public class CheckDMaaPEventsManager {
+
+ public static final String RESPONSE_STATUS = "response status : ";
+ public static final String RETURNS = " returns ";
+ public static final String ERROR_ON_CALLING = "error on calling ";
+
+ @Autowired
+ private RestTemplate restTemplate;
+
+ @Autowired
+ private SubscriberRepository subscriberRepository;
+
+ @Autowired
+ private NotifierService notifier;
+
+ @Value("${dmaap.host}")
+ private String dmaapHostname;
+
+ @Value("${dmaap.topic}")
+ private String topic;
+
+ @Value("${dmaap.consumergroup}")
+ private String consumerGroup;
+
+ @Value("${dmaap.consumerid}")
+ private String consumerId;
+
+ @Value("${dmaap.timeout}")
+ private String timeout;
+
+ private final Logger logger = LoggerFactory.getLogger(CheckDMaaPEventsManager.class);
+
+ private String dmaapGetEventsUrl;
+
+ @PostConstruct
+ private void setUpAndLogDMaaPUrl() {
+ dmaapGetEventsUrl = new StringBuilder().append(dmaapHostname)
+ .append(OnapComponentsUrlPaths.DMAAP_CONSUME_EVENTS).toString();
+ logger.info("DMaaP Get Events url : " + dmaapGetEventsUrl);
+ }
+
+ public void checkForDMaaPAAIEvents() {
+ ObjectMapper mapper = new ObjectMapper();
+
+
+ String dmaapGetEventsUrlFormated = dmaapGetEventsUrl.replace("$topic", topic);
+ dmaapGetEventsUrlFormated = dmaapGetEventsUrlFormated.replace("$consumergroup", consumerGroup);
+ dmaapGetEventsUrlFormated = dmaapGetEventsUrlFormated.replace("$consumerid", consumerId);
+ dmaapGetEventsUrlFormated = dmaapGetEventsUrlFormated.replace("$timeout", timeout);
+
+ List<String> dmaapResponse = callDMaaPGetEvents(dmaapGetEventsUrlFormated);
+ if (!CollectionUtils.isEmpty(dmaapResponse)) {
+ for (int i = 0; i < dmaapResponse.size(); i++) {
+ String aaiEventString = dmaapResponse.get(i);
+ if (logger.isDebugEnabled()) {
+ logger.debug("aai event returned was {}", aaiEventString);
+ }
+ try {
+ JsonNode jsonNode = mapper.readValue(aaiEventString, JsonNode.class);
+ JsonNode eventHeader = jsonNode.get("event-header");
+ String aaiEventEntityType = eventHeader.get("entity-type").asText();
+ String action = eventHeader.get("action").asText();
+ if (logger.isDebugEnabled()) {
+ logger.debug("aaiEventEntityType is {} and action is {}", aaiEventEntityType, action);
+ }
+ if (aaiEventEntityType.equals("service-instance")) {
+ {
+ // parse the AAI-EVENT service-instance tree
+ ServiceInstanceEvent serviceInstanceEvent = new ServiceInstanceEvent();
+ RelatedParty relatedParty = new RelatedParty();
+ JsonNode entity = jsonNode.get("entity");
+ relatedParty.setId(entity.get("global-customer-id").asText());
+ relatedParty.setName(entity.get("subscriber-name").asText());
+ serviceInstanceEvent.setRelatedParty(relatedParty);
+ JsonNode childServiceSubscription = entity.get("service-subscriptions");
+ JsonNode serviceSubscriptions = childServiceSubscription.get("service-subscription");
+ JsonNode serviceSubscription = serviceSubscriptions.get(0);
+ String serviceSubscriptionPrint = serviceSubscription.toString();
+ JsonNode childserviceInstances = serviceSubscription.get("service-instances");
+ JsonNode serviceInstances = childserviceInstances.get("service-instance");
+ JsonNode serviceInstance = serviceInstances.get(0);
+ serviceInstanceEvent.setId(serviceInstance.get("service-instance-id").asText());
+ serviceInstanceEvent.setState(serviceInstance.get("orchestration-status").asText());
+ if (action.equals("CREATE")) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("sending service inventory event to listeners");
+ }
+ processEvent(
+ EventFactory.getEvent(EventType.SERVICE_CREATION, serviceInstanceEvent));
+ } else if (action.equals("DELETE")) {
+ processEvent(EventFactory.getEvent(EventType.SERVICE_REMOVE, serviceInstanceEvent));
+ } else if (action.equals("UPDATE")) {
+ processEvent(EventFactory.getEvent(EventType.SERVICE_ATTRIBUTE_VALUE_CHANGE,
+ serviceInstanceEvent));
+ }
+
+
+ }
+
+ }
+
+ } catch (JsonParseException e) {
+ logger.error(" unable to Parse AAI Event JSON String {}, exception is", aaiEventString,
+ e.getMessage());
+ } catch (JsonMappingException e) {
+ logger.error(" unable to Map AAI Event JSON String {} to Java Pojo, exception is",
+ aaiEventString, e.getMessage());
+ } catch (IOException e) {
+ logger.error("IO Error when parsing AAI Event JSON String {} ", aaiEventString,
+ e.getMessage());
+ }
+ }
+ }
+ }
+
+ public List<String> callDMaaPGetEvents(String dmaapGetEventsUrlFormated) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Calling DMaaP Url : " + dmaapGetEventsUrlFormated);
+ }
+ UriComponentsBuilder callURI = UriComponentsBuilder.fromHttpUrl(dmaapGetEventsUrlFormated);
+ ResponseEntity<Object> response = callDMaaP(callURI.build().encode().toUri());
+ return (List<String>) response.getBody();
+
+ }
+
+ private ResponseEntity<Object> callDMaaP(URI callURI) {
+ ResponseEntity<Object> response =
+ restTemplate.exchange(callURI, HttpMethod.GET, buildRequestHeader(), Object.class);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("response body : {} ", response.getBody().toString());
+ logger.debug("response status : {}", response.getStatusCodeValue());
+ }
+ return response;
+ }
+
+ private HttpEntity<String> buildRequestHeader() {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.add("Accept", "application/json");
+ httpHeaders.add("Content-Type", "application/json");
+ return new HttpEntity<>("parameters", httpHeaders);
+ }
+
+ /**
+ * Retrieve subscribers that match an event and fire notification asynchronously
+ *
+ * @param event
+ */
+ private void processEvent(Event event) {
+ subscriberRepository.findSubscribersUsingEvent(event).forEach(sub -> notifier.run(sub, event));
+ }
+
+}
diff --git a/src/main/java/org/onap/nbi/apis/hub/service/DMaaPEventsScheduler.java b/src/main/java/org/onap/nbi/apis/hub/service/DMaaPEventsScheduler.java
new file mode 100644
index 0000000..20bc2d9
--- /dev/null
+++ b/src/main/java/org/onap/nbi/apis/hub/service/DMaaPEventsScheduler.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2019 Huawei
+ *
+ * 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.
+ */
+
+package org.onap.nbi.apis.hub.service;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+@Profile("default")
+@Service
+@EnableScheduling
+public class DMaaPEventsScheduler {
+
+ @Autowired
+ CheckDMaaPEventsManager checkDMaaPEventsManager;
+
+ @Scheduled(fixedDelayString = "${dmaapCheck.schedule}",
+ initialDelayString = "${dmaapCheck.initial}")
+ private void processDMaaPEvents() {
+ checkDMaaPEventsManager.checkForDMaaPAAIEvents();
+
+ }
+}
+
diff --git a/src/main/java/org/onap/nbi/apis/hub/service/EventFactory.java b/src/main/java/org/onap/nbi/apis/hub/service/EventFactory.java
index e935a1c..ed34322 100644
--- a/src/main/java/org/onap/nbi/apis/hub/service/EventFactory.java
+++ b/src/main/java/org/onap/nbi/apis/hub/service/EventFactory.java
@@ -1,75 +1,95 @@
/**
* Copyright (c) 2018 Orange
*
- * 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
+ * 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.
+ * 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.
*/
package org.onap.nbi.apis.hub.service;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.MappingJsonFactory;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import org.onap.nbi.apis.hub.model.Event;
import org.onap.nbi.apis.hub.model.EventType;
+import org.onap.nbi.apis.hub.model.ServiceInstanceEvent;
import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
import org.onap.nbi.commons.JacksonFilter;
import org.onap.nbi.commons.JsonRepresentation;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.MappingJsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
public class EventFactory {
- private static final ObjectMapper mapper = new ObjectMapper(new MappingJsonFactory());
+ private static final ObjectMapper mapper = new ObjectMapper(new MappingJsonFactory());
- public static Event getEvent(EventType eventType, ServiceOrder serviceOrder, ServiceOrderItem serviceOrderItem) {
- Event event = new Event();
- event.setEventId(UUID.randomUUID().toString());
- event.setEventDate(new Date());
- event.setEventType(eventType.value());
+ public static Event getEvent(EventType eventType, ServiceOrder serviceOrder,
+ ServiceOrderItem serviceOrderItem) {
+ Event event = new Event();
+ event.setEventId(UUID.randomUUID().toString());
+ event.setEventDate(new Date());
+ event.setEventType(eventType.value());
- DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
- mapper.setDateFormat(df);
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+ mapper.setDateFormat(df);
- JsonNode serviceOrderJson = mapper.valueToTree(filterServiceOrder(serviceOrder));
+ JsonNode serviceOrderJson = mapper.valueToTree(filterServiceOrder(serviceOrder));
- if (EventType.SERVICE_ORDER_ITEM_STATE_CHANGE.equals(eventType)) {
- JsonNode serviceOrderItemJson = mapper.valueToTree(serviceOrderItem);
- ((ObjectNode) serviceOrderJson).putArray("orderItem").add(serviceOrderItemJson);
- }
+ if (EventType.SERVICE_ORDER_ITEM_STATE_CHANGE.equals(eventType)) {
+ JsonNode serviceOrderItemJson = mapper.valueToTree(serviceOrderItem);
+ ((ObjectNode) serviceOrderJson).putArray("orderItem").add(serviceOrderItemJson);
+ }
- event.setEvent(serviceOrderJson);
+ event.setEvent(serviceOrderJson);
- return event;
- }
+ return event;
+ }
+
+ public static Event getEvent(EventType eventType, ServiceInstanceEvent serviceInstanceEvent) {
+ Event event = new Event();
+ event.setEventId(UUID.randomUUID().toString());
+ event.setEventDate(new Date());
+ event.setEventType(eventType.value());
+
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+ mapper.setDateFormat(df);
+ JsonNode serviceInstanceJson = mapper.valueToTree(serviceInstanceEvent);
- /**
- * Filter ServiceOrderObject to produce a lightweight object that fit the eventBody specification
- * @param serviceOrder
- * @return
- */
- private static Object filterServiceOrder(final ServiceOrder serviceOrder) {
+ event.setEvent(serviceInstanceJson);
- Object filteredServiceOrder = null;
+ return event;
+ }
- if (serviceOrder != null) {
- JsonRepresentation jsonRepresentation = new JsonRepresentation();
- jsonRepresentation.add("id").add("href").add("externalId").add("state").add("orderDate").add
- ("completionDateTime").add("orderItem");
- filteredServiceOrder = JacksonFilter.createNode(serviceOrder, jsonRepresentation);
- }
+ /**
+ * Filter ServiceOrderObject to produce a lightweight object that fit the eventBody specification
+ *
+ * @param serviceOrder
+ * @return
+ */
+ private static Object filterServiceOrder(final ServiceOrder serviceOrder) {
- return filteredServiceOrder;
+ Object filteredServiceOrder = null;
+
+ if (serviceOrder != null) {
+ JsonRepresentation jsonRepresentation = new JsonRepresentation();
+ jsonRepresentation.add("id").add("href").add("externalId").add("state").add("orderDate")
+ .add("completionDateTime").add("orderItem");
+
+ filteredServiceOrder = JacksonFilter.createNode(serviceOrder, jsonRepresentation);
}
+
+ return filteredServiceOrder;
+ }
}
diff --git a/src/main/java/org/onap/nbi/apis/hub/service/NotifierService.java b/src/main/java/org/onap/nbi/apis/hub/service/NotifierService.java
index 90cc7a4..80b6331 100755
--- a/src/main/java/org/onap/nbi/apis/hub/service/NotifierService.java
+++ b/src/main/java/org/onap/nbi/apis/hub/service/NotifierService.java
@@ -1,14 +1,15 @@
/**
* Copyright (c) 2018 Orange
*
- * 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
+ * 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.
+ * 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.
*/
package org.onap.nbi.apis.hub.service;
@@ -26,19 +27,19 @@ import org.springframework.web.client.RestTemplate;
@Service
public class NotifierService {
- private final Logger logger = LoggerFactory.getLogger(NotifierService.class);
+ private final Logger logger = LoggerFactory.getLogger(NotifierService.class);
- @Autowired
- RestTemplate restTemplate;
-
- @Async
- public void run(Subscriber subscriber, @Valid Event event) {
- try {
- restTemplate.postForEntity(subscriber.getCallback(), event, Object.class);
- } catch (BackendFunctionalException e) {
- logger.error(" unable to post event to {} , receive {}, {}", subscriber.getCallback(), e.getHttpStatus(),
- e.getBodyResponse());
- }
+ @Autowired
+ RestTemplate restTemplate;
+ @Async
+ public void run(Subscriber subscriber, @Valid Event event) {
+ try {
+ restTemplate.postForEntity(subscriber.getCallback(), event, Object.class);
+ } catch (BackendFunctionalException e) {
+ logger.error(" unable to post event to {} , receive {}, {}", subscriber.getCallback(),
+ e.getHttpStatus(), e.getBodyResponse());
}
+
+ }
}
diff --git a/src/main/java/org/onap/nbi/configuration/AppContext.java b/src/main/java/org/onap/nbi/configuration/AppContext.java
new file mode 100644
index 0000000..fb26799
--- /dev/null
+++ b/src/main/java/org/onap/nbi/configuration/AppContext.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2019 Huawei
+ *
+ * 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.
+ */
+
+package org.onap.nbi.configuration;
+
+import java.util.concurrent.Executor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.task.SimpleAsyncTaskExecutor;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+@Configuration
+@EnableAsync
+public class AppContext extends WebMvcConfigurationSupport {
+ @Bean
+ public Executor taskExecutor() {
+ return new SimpleAsyncTaskExecutor();
+ }
+}
diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties
index b959b47..ca04a05 100644
--- a/src/main/resources/application-test.properties
+++ b/src/main/resources/application-test.properties
@@ -60,6 +60,13 @@ so.owning.entity.id = 6b5b6b70-4e9a-4f6f-8b7b-cbd7cf990c6e
so.owning.entity.name = OE-generic
so.project.name = Project-generic
+# DMAAP
+dmaap.host = http://127.0.0.1:8091
+dmaap.topic = AAI-EVENT
+dmaap.consumergroup = NBICG1
+dmaap.consumerid = NBIC1
+dmaap.timeout = 2000
+
# MSB
msb.enabled = false
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 633e029..70d640c 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -44,6 +44,8 @@ serviceOrder.schedule = 5000
serviceOrder.initial = 1
executionTask.schedule = 2000
executionTask.initial = 1
+dmaapCheck.schedule = 10000
+dmaapCheck.initial = 1
# SDC
sdc.host = http://10.0.3.1:8080
@@ -64,6 +66,13 @@ so.owning.entity.id = 6b5b6b70-4e9a-4f6f-8b7b-cbd7cf990c6e
so.owning.entity.name = OE-generic
so.project.name = Project-generic
+# DMAAP
+dmaap.host = http://10.0.6.1:3904
+dmaap.topic = AAI-EVENT
+dmaap.consumergroup = NBICG1
+dmaap.consumerid = NBIC1
+dmaap.timeout = 2000
+
# MSB
msb.enabled = true
msb.discovery.host = msb_discovery
diff --git a/src/test/java/org/onap/nbi/api/listener/ListenerResource.java b/src/test/java/org/onap/nbi/api/listener/ListenerResource.java
index 1b60109..8fb276d 100644
--- a/src/test/java/org/onap/nbi/api/listener/ListenerResource.java
+++ b/src/test/java/org/onap/nbi/api/listener/ListenerResource.java
@@ -1,18 +1,18 @@
/**
* Copyright (c) 2019 Orange
*
- * 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
+ * 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.
+ * 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.
*/
package org.onap.nbi.api.listener;
-import com.fasterxml.jackson.databind.JsonNode;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
@@ -34,81 +34,97 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+import com.fasterxml.jackson.databind.JsonNode;
@RestController
@RequestMapping("/test/listener")
public class ListenerResource extends ResourceManagement {
- Logger logger = LoggerFactory.getLogger(ListenerResource.class);
-
- static Map<String, JsonNode> events = new ConcurrentHashMap<>();
+ Logger logger = LoggerFactory.getLogger(ListenerResource.class);
- /*
- listener resource test for hub resource
- */
- @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity<JsonNode> postListener(@RequestBody JsonNode event) {
- if (logger.isDebugEnabled()) {
- logger.debug("POST event from nbi : {}", event.toString());
- }
- String eventId = event.get("eventId").asText();
- events.put(eventId, event);
-
- URI location = ServletUriComponentsBuilder
- .fromCurrentRequest()
- .path("/{id}")
- .buildAndExpand(eventId)
- .toUri();
+ static Map<String, JsonNode> events = new ConcurrentHashMap<>();
- return ResponseEntity.created(location).body(event);
+ /*
+ * listener resource test for hub resource
+ */
+ @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity<JsonNode> postListener(@RequestBody JsonNode event) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("POST event from nbi : {}", event.toString());
}
-
-
- @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity<Collection<JsonNode>> findEvents(@RequestParam MultiValueMap<String, String> params) {
- Collection<JsonNode> values = new ArrayList<>();
- String serviceOrderId = params.getFirst("serviceOrderId");
- if(StringUtils.isNotEmpty(serviceOrderId)) {
- for (JsonNode jsonNode : events.values()) {
- String id = jsonNode.get("event").get("id").asText();
- logger.info("found event with service order id : "+id);
- if(id.equals(serviceOrderId)) {
- values.add(jsonNode);
- }
- }
- if(!values.isEmpty()) {
- return ResponseEntity.ok(values);
- } else {
- logger.error("cannot found events with service order id : "+serviceOrderId);
- return ResponseEntity.notFound().build();
- }
- } else {
- values=events.values();
+ String eventId = event.get("eventId").asText();
+ logger.info("putting eventId {} in the events map", eventId);
+ events.put(eventId, event);
+
+ URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
+ .buildAndExpand(eventId).toUri();
+
+ return ResponseEntity.created(location).body(event);
+ }
+
+
+ @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity<Collection<JsonNode>> findEvents(
+ @RequestParam MultiValueMap<String, String> params) {
+ logger.info("called listener get with params {} : " + params.toString());
+ Collection<JsonNode> values = new ArrayList<>();
+ String serviceOrderId = params.getFirst("serviceOrderId");
+ String serviceInstanceId = params.getFirst("serviceInstanceId");
+ if (StringUtils.isNotEmpty(serviceOrderId)) {
+ for (JsonNode jsonNode : events.values()) {
+ String id = jsonNode.get("event").get("id").asText();
+ logger.info("found event with service order id : " + id);
+ if (id.equals(serviceOrderId)) {
+ values.add(jsonNode);
+ }
+ }
+ if (!values.isEmpty()) {
+ return ResponseEntity.ok(values);
+ } else {
+ logger.error("cannot found events with service order id : " + serviceOrderId);
+ return ResponseEntity.notFound().build();
+ }
+ } else if (StringUtils.isNotEmpty(serviceInstanceId)) {
+ for (JsonNode jsonNode : events.values()) {
+ String id = jsonNode.get("event").get("id").asText();
+ logger.info("found event with service Instance id : " + id);
+ if (id.equals(serviceInstanceId)) {
+ values.add(jsonNode);
}
+ }
+ if (!values.isEmpty()) {
return ResponseEntity.ok(values);
+ } else {
+ logger.error("cannot found events with service instance id : " + serviceInstanceId);
+ return ResponseEntity.notFound().build();
+ }
+ } else {
+ values = events.values();
}
+ return ResponseEntity.ok(values);
+ }
- @GetMapping(value = "/{eventId}", produces = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity<Object> getEvent(@PathVariable String eventId) {
+ @GetMapping(value = "/{eventId}", produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity<Object> getEvent(@PathVariable String eventId) {
- return ResponseEntity.ok(events.get(eventId));
+ return ResponseEntity.ok(events.get(eventId));
- }
+ }
- @DeleteMapping(value = "/{eventId}", produces = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity<Object> deleteEvent(@PathVariable String eventId) {
+ @DeleteMapping(value = "/{eventId}", produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity<Object> deleteEvent(@PathVariable String eventId) {
- events.remove(eventId);
- return ResponseEntity.noContent().build();
+ events.remove(eventId);
+ return ResponseEntity.noContent().build();
- }
+ }
- @DeleteMapping(produces = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity<Object> deleteEvents() {
+ @DeleteMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity<Object> deleteEvents() {
- events.clear();
- return ResponseEntity.noContent().build();
+ events.clear();
+ return ResponseEntity.noContent().build();
- }
+ }
}
diff --git a/src/test/resources/karatetest/features/03--Subscriber.feature b/src/test/resources/karatetest/features/03--Subscriber.feature
index 6e4b884..e4704ea 100644
--- a/src/test/resources/karatetest/features/03--Subscriber.feature
+++ b/src/test/resources/karatetest/features/03--Subscriber.feature
@@ -154,4 +154,98 @@ When method delete
Then status 204
Given path 'serviceOrder',serviceOrderId
When method delete
+Then status 204
+
+
+Scenario: testSubscriberWithTestListenerForServiceInventorCreationEvents
+* def listenerUrl = nbiBaseUrl + "/test/listener"
+Given path 'test/listener'
+When method delete
+Then status 204
+Given path 'hub'
+And request { id : 'id', callback : '#(listenerUrl)' , query : 'eventType = ServiceCreationNotification' }
+When method post
+Then status 201
+Given path 'hub'
+When method get
+And def hubId = $[0].id
+Given path 'hub/testaaievents'
+Then status 200
+When method get
+Given path 'test/listener'
+And params {serviceInstanceId : 'new-test5'}
+And retry until responseStatus == 200
+When method get
+And assert response.length == 1
+And match $[0] contains { eventId : '#notnull' , eventType : 'ServiceCreationNotification' , eventDate : '#notnull' , event :'#notnull'}
+And def eventId = $[0].eventId
+And def eventDate = $[0].eventDate
+And call checkDateFormat(eventDate)
+Given path 'hub',hubId
+When method delete
+Then status 204
+Given path 'test/listener',eventId
+When method delete
+Then status 204
+
+Scenario: testSubscriberWithTestListenerForServiceInventoryUpdateEvents
+* def listenerUrl = nbiBaseUrl + "/test/listener"
+Given path 'test/listener'
+When method delete
+Then status 204
+Given path 'hub'
+And request { id : 'id', callback : '#(listenerUrl)' , query : 'eventType = ServiceAttributeValueChangeNotification' }
+When method post
+Then status 201
+Given path 'hub'
+When method get
+And def hubId = $[0].id
+Given path 'hub/testaaievents'
+Then status 200
+When method get
+Given path 'test/listener'
+And params {serviceInstanceId : 'new-test5'}
+And retry until responseStatus == 200
+When method get
+And assert response.length == 1
+And match $[0] contains { eventId : '#notnull' , eventType : 'ServiceAttributeValueChangeNotification' , eventDate : '#notnull' , event :'#notnull'}
+And def eventId = $[0].eventId
+And def eventDate = $[0].eventDate
+And call checkDateFormat(eventDate)
+Given path 'hub',hubId
+When method delete
+Then status 204
+Given path 'test/listener',eventId
+When method delete
+Then status 204
+
+Scenario: testSubscriberWithTestListenerForServiceInventoryRemoveEvents
+* def listenerUrl = nbiBaseUrl + "/test/listener"
+Given path 'test/listener'
+When method delete
+Then status 204
+Given path 'hub'
+And request { id : 'id', callback : '#(listenerUrl)' , query : 'eventType = ServiceRemoveNotification' }
+When method post
+Then status 201
+Given path 'hub'
+When method get
+And def hubId = $[0].id
+Given path 'hub/testaaievents'
+Then status 200
+When method get
+Given path 'test/listener'
+And params {serviceInstanceId : 'new-test5'}
+And retry until responseStatus == 200
+When method get
+And assert response.length == 1
+And match $[0] contains { eventId : '#notnull' , eventType : 'ServiceRemoveNotification' , eventDate : '#notnull' , event :'#notnull'}
+And def eventId = $[0].eventId
+And def eventDate = $[0].eventDate
+And call checkDateFormat(eventDate)
+Given path 'hub',hubId
+When method delete
+Then status 204
+Given path 'test/listener',eventId
+When method delete
Then status 204 \ No newline at end of file
diff --git a/src/test/resources/mappings/dmaap_get_aaievents.json b/src/test/resources/mappings/dmaap_get_aaievents.json
new file mode 100644
index 0000000..6b5c630
--- /dev/null
+++ b/src/test/resources/mappings/dmaap_get_aaievents.json
@@ -0,0 +1,16 @@
+{
+ "request": {
+ "method": "GET",
+ "url": "/events/AAI-EVENT/NBICG1/NBIC1?timeout=2000"
+ },
+ "response": {
+ "status": 200,
+ "jsonBody": [
+ "{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"service-instance\",\"top-entity-type\":\"customer\",\"entity-link\":\"/aai/v14/business/customers/customer/testcustomer2/service-subscriptions/service-subscription/HSIA_Service/service-instances/service-instance/new-test5\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"CREATE\",\"sequence-number\":\"0\",\"id\":\"c3654954-9802-4b46-a397-6e12c74d2254\",\"source-name\":\"AAI\",\"version\":\"v14\",\"timestamp\":\"20190301-10:20:47:154\"},\"entity\":{\"global-customer-id\":\"testcustomer2\",\"subscriber-name\":\"testcustomer2\",\"service-subscriptions\":{\"service-subscription\":[{\"service-type\":\"HSIA_Service\",\"service-instances\":{\"service-instance\":[{\"service-instance-id\":\"new-test5\",\"resource-version\":\"1551435647134\",\"service-instance-name\":\"testname\",\"orchestration-status\":\"assigned\"}]}}]}}}",
+ "{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"service-instance\",\"top-entity-type\":\"customer\",\"entity-link\":\"/aai/v14/business/customers/customer/testcustomer2/service-subscriptions/service-subscription/HSIA_Service/service-instances/service-instance/new-test5\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"UPDATE\",\"sequence-number\":\"0\",\"id\":\"a746584a-72b7-4994-97b2-bc43ec24fd35\",\"source-name\":\"AAI\",\"version\":\"v14\",\"timestamp\":\"20190301-13:50:34:121\"},\"entity\":{\"global-customer-id\":\"testcustomer2\",\"subscriber-name\":\"testcustomer2\",\"service-subscriptions\":{\"service-subscription\":[{\"service-type\":\"HSIA_Service\",\"service-instances\":{\"service-instance\":[{\"service-instance-id\":\"new-test5\",\"resource-version\":\"1551448234103\",\"service-instance-name\":\"testname\",\"orchestration-status\":\"active\"}]}}]}}}","{\"cambria.partition\":\"AAI\",\"event-header\":{\"severity\":\"NORMAL\",\"entity-type\":\"service-instance\",\"top-entity-type\":\"customer\",\"entity-link\":\"/aai/v14/business/customers/customer/testcustomer2/service-subscriptions/service-subscription/HSIA_Service/service-instances/service-instance/new-test5\",\"event-type\":\"AAI-EVENT\",\"domain\":\"dev\",\"action\":\"DELETE\",\"sequence-number\":\"0\",\"id\":\"011c139e-d00f-4a55-b1fc-b319f16e0f70\",\"source-name\":\"AAI\",\"version\":\"v14\",\"timestamp\":\"20190301-13:53:09:590\"},\"entity\":{\"global-customer-id\":\"testcustomer2\",\"subscriber-name\":\"testcustomer2\",\"service-subscriptions\":{\"service-subscription\":[{\"service-type\":\"HSIA_Service\",\"service-instances\":{\"service-instance\":[{\"service-instance-id\":\"new-test5\",\"resource-version\":\"1551448234103\",\"service-instance-name\":\"testname\",\"orchestration-status\":\"active\"}]}}]}}}"
+ ],
+ "headers": {
+ "Content-Type": "application/json"
+ }
+ }
+}