aboutsummaryrefslogtreecommitdiffstats
path: root/aai-core/src
diff options
context:
space:
mode:
Diffstat (limited to 'aai-core/src')
-rw-r--r--aai-core/src/main/java/org/onap/aai/prevalidation/ValidationService.java140
-rw-r--r--aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java33
-rw-r--r--aai-core/src/main/java/org/onap/aai/rest/ueb/UEBNotification.java75
-rw-r--r--aai-core/src/test/java/org/onap/aai/AAISetup.java4
-rw-r--r--aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java51
5 files changed, 157 insertions, 146 deletions
diff --git a/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationService.java b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationService.java
index 70e16e27..939c8389 100644
--- a/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationService.java
+++ b/aai-core/src/main/java/org/onap/aai/prevalidation/ValidationService.java
@@ -29,6 +29,7 @@ import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -46,7 +47,6 @@ import org.onap.aai.rest.ueb.NotificationEvent;
import org.onap.aai.restclient.RestClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
@@ -63,55 +63,33 @@ import org.springframework.stereotype.Service;
@Profile("pre-validation")
public class ValidationService {
- /**
- * Error indicating that the service trying to connect is down
- */
static final String CONNECTION_REFUSED_STRING =
"Connection refused to the validation microservice due to service unreachable";
-
- /**
- * Error indicating that the server is unable to reach the port
- * Could be server related connectivity issue
- */
static final String CONNECTION_TIMEOUT_STRING = "Connection timeout to the validation microservice as this could "
+ "indicate the server is unable to reach port, "
+ "please check on server by running: nc -w10 -z -v ${VALIDATION_HOST} ${VALIDATION_PORT}";
-
- /**
- * Error indicating that the request exceeded the allowed time
- *
- * Note: This means that the service could be active its
- * just taking some time to process our request
- */
static final String REQUEST_TIMEOUT_STRING =
"Request to validation service took longer than the currently set timeout";
-
static final String VALIDATION_ENDPOINT = "/v1/validate";
static final String VALIDATION_HEALTH_ENDPOINT = "/v1/info";
+ private static final Logger LOGGER = LoggerFactory.getLogger(ValidationService.class);
private static final String ENTITY_TYPE = "entity-type";
private static final String ACTION = "action";
private static final String SOURCE_NAME = "source-name";
-
private static final String DELETE = "DELETE";
- private static final Logger LOGGER = LoggerFactory.getLogger(ValidationService.class);
-
private final RestClient validationRestClient;
-
private final String appName;
-
private final Set<String> validationNodeTypes;
+ private final Gson gson;
private List<Pattern> exclusionList;
- private final Gson gson;
-
- @Autowired
public ValidationService(@Qualifier("validationRestClient") RestClient validationRestClient,
@Value("${spring.application.name}") String appName,
@Value("${validation.service.node-types}") String validationNodes,
- @Value("${validation.service.exclusion-regexes}") String exclusionRegexes) {
+ @Value("${validation.service.exclusion-regexes:#{null}}") String exclusionRegexes) {
this.validationRestClient = validationRestClient;
this.appName = appName;
@@ -129,20 +107,19 @@ public class ValidationService {
@PostConstruct
public void initialize() throws AAIException {
+ doHealthCheckRequest();
+ }
+ private void doHealthCheckRequest() throws AAIException {
Map<String, String> httpHeaders = new HashMap<>();
-
httpHeaders.put("X-FromAppId", appName);
httpHeaders.put("X-TransactionID", UUID.randomUUID().toString());
httpHeaders.put("Content-Type", "application/json");
ResponseEntity<String> healthCheckResponse = null;
-
try {
-
healthCheckResponse =
validationRestClient.execute(VALIDATION_HEALTH_ENDPOINT, HttpMethod.GET, httpHeaders, null);
-
} catch (Exception ex) {
AAIException validationException = new AAIException("AAI_4021", ex);
throw validationException;
@@ -160,50 +137,29 @@ public class ValidationService {
}
public void validate(List<NotificationEvent> notificationEvents) throws AAIException {
-
- if (notificationEvents == null || notificationEvents.isEmpty()) {
+ if (notificationEvents == null || notificationEvents.isEmpty() || isSourceExcluded(notificationEvents)) {
return;
}
- {
- // Get the first notification and if the source of that notification
- // is in one of the regexes then we skip sending it to validation
- NotificationEvent notification = notificationEvents.get(0);
- Introspector eventHeader = notification.getEventHeader();
- if (eventHeader != null) {
- String source = eventHeader.getValue(SOURCE_NAME);
- for (Pattern pattern : exclusionList) {
- if (pattern.matcher(source).matches()) {
- return;
- }
- }
- }
-
- }
-
for (NotificationEvent event : notificationEvents) {
-
Introspector eventHeader = event.getEventHeader();
-
if (eventHeader == null) {
// Should I skip processing the request and let it continue
// or fail the request and cause client impact
continue;
}
- String entityType = eventHeader.getValue(ENTITY_TYPE);
- String action = eventHeader.getValue(ACTION);
-
- /**
+ /*
* Skipping the delete events for now
* Note: Might revisit this later when validation supports DELETE events
*/
- if (DELETE.equalsIgnoreCase(action)) {
+ if (isDelete(eventHeader)) {
continue;
}
+ String entityType = eventHeader.getValue(ENTITY_TYPE);
if (this.shouldValidate(entityType)) {
- List<String> violations = this.preValidate(event.getNotificationEvent());
+ List<String> violations = preValidate(event.getNotificationEvent());
if (!violations.isEmpty()) {
AAIException aaiException = new AAIException("AAI_4019");
aaiException.getTemplateVars().addAll(violations);
@@ -213,10 +169,33 @@ public class ValidationService {
}
}
- List<String> preValidate(String body) throws AAIException {
+ /**
+ * Determine if event is of type delete
+ */
+ private boolean isDelete(Introspector eventHeader) {
+ String action = eventHeader.getValue(ACTION);
+ return DELETE.equalsIgnoreCase(action);
+ }
+
+ /**
+ * Checks the `source` attribute of the first event to determine if validation should be skipped
+ * @param notificationEvents
+ * @return
+ */
+ private boolean isSourceExcluded(List<NotificationEvent> notificationEvents) {
+ // Get the first notification and if the source of that notification
+ // is in one of the regexes then we skip sending it to validation
+ NotificationEvent notification = notificationEvents.get(0);
+ Introspector eventHeader = notification.getEventHeader();
+ if (eventHeader != null) {
+ String source = eventHeader.getValue(SOURCE_NAME);
+ return exclusionList.stream().anyMatch(pattern -> pattern.matcher(source).matches());
+ }
+ return false;
+ }
+ public List<String> preValidate(String body) throws AAIException {
Map<String, String> httpHeaders = new HashMap<>();
-
httpHeaders.put("X-FromAppId", appName);
httpHeaders.put("X-TransactionID", UUID.randomUUID().toString());
httpHeaders.put("Content-Type", "application/json");
@@ -224,26 +203,19 @@ public class ValidationService {
List<String> violations = new ArrayList<>();
ResponseEntity<String> responseEntity;
try {
-
responseEntity = validationRestClient.execute(VALIDATION_ENDPOINT, HttpMethod.POST, httpHeaders, body);
-
Object responseBody = responseEntity.getBody();
if (isSuccess(responseEntity)) {
LOGGER.debug("Validation Service returned following response status code {} and body {}",
responseEntity.getStatusCodeValue(), responseEntity.getBody());
} else if (responseBody != null) {
- Validation validation = null;
- try {
- validation = gson.fromJson(responseBody.toString(), Validation.class);
- } catch (JsonSyntaxException jsonException) {
- LOGGER.warn("Unable to convert the response body {}", jsonException.getMessage());
- }
+ Validation validation = getValidation(responseBody);
if (validation == null) {
LOGGER.debug("Validation Service following status code {} with body {}",
responseEntity.getStatusCodeValue(), responseEntity.getBody());
} else {
- violations.addAll(extractViolations(validation));
+ violations = extractViolations(validation);
}
} else {
LOGGER.warn("Unable to convert the response body null");
@@ -267,27 +239,27 @@ public class ValidationService {
return violations;
}
+ private Validation getValidation(Object responseBody) {
+ Validation validation = null;
+ try {
+ validation = gson.fromJson(responseBody.toString(), Validation.class);
+ } catch (JsonSyntaxException jsonException) {
+ LOGGER.warn("Unable to convert the response body {}", jsonException.getMessage());
+ }
+ return validation;
+ }
+
boolean isSuccess(ResponseEntity<String> responseEntity) {
return responseEntity != null && responseEntity.getStatusCode().is2xxSuccessful();
}
- List<String> extractViolations(Validation validation) {
-
- List<String> errorMessages = new ArrayList<>();
-
- if (validation == null) {
- return errorMessages;
+ public List<String> extractViolations(Validation validation) {
+ if (validation == null || validation.getViolations() == null) {
+ return Collections.emptyList();
}
-
- List<Violation> violations = validation.getViolations();
-
- if (violations != null && !violations.isEmpty()) {
- for (Violation violation : validation.getViolations()) {
- LOGGER.info(violation.getErrorMessage());
- errorMessages.add(violation.getErrorMessage());
- }
- }
-
- return errorMessages;
+ return validation.getViolations().stream()
+ .map(Violation::getErrorMessage)
+ .peek(LOGGER::info)
+ .collect(Collectors.toList());
}
}
diff --git a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
index 28d66dd0..7ecdd6d5 100644
--- a/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
+++ b/aai-core/src/main/java/org/onap/aai/rest/db/HttpEntry.java
@@ -155,49 +155,22 @@ public class HttpEntry {
}
public HttpEntry setHttpEntryProperties(SchemaVersion version, String serverBase) {
- this.version = version;
- this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version);
- this.dbEngine = new JanusGraphDBEngine(queryStyle, loader);
-
- getDbEngine().startTransaction();
- this.notification = new UEBNotification(loader, loaderFactory, schemaVersions);
- if ("true".equals(AAIConfig.get("aai.notification.depth.all.enabled", "true"))) {
- this.notificationDepth = AAIProperties.MAXIMUM_DEPTH;
- } else {
- this.notificationDepth = AAIProperties.MINIMUM_DEPTH;
- }
-
+ setHttpEntryProperties(version);
this.serverBase = serverBase;
return this;
}
public HttpEntry setHttpEntryProperties(SchemaVersion version, UEBNotification notification) {
- this.version = version;
- this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version);
- this.dbEngine = new JanusGraphDBEngine(queryStyle, loader);
-
+ setHttpEntryProperties(version);
this.notification = notification;
-
- if ("true".equals(AAIConfig.get("aai.notification.depth.all.enabled", "true"))) {
- this.notificationDepth = AAIProperties.MAXIMUM_DEPTH;
- } else {
- this.notificationDepth = AAIProperties.MINIMUM_DEPTH;
- }
- // start transaction on creation
- getDbEngine().startTransaction();
return this;
}
public HttpEntry setHttpEntryProperties(SchemaVersion version, UEBNotification notification,
int notificationDepth) {
- this.version = version;
- this.loader = loaderFactory.createLoaderForVersion(introspectorFactoryType, version);
- this.dbEngine = new JanusGraphDBEngine(queryStyle, loader);
-
+ setHttpEntryProperties(version);
this.notification = notification;
this.notificationDepth = notificationDepth;
- // start transaction on creation
- getDbEngine().startTransaction();
return this;
}
diff --git a/aai-core/src/main/java/org/onap/aai/rest/ueb/UEBNotification.java b/aai-core/src/main/java/org/onap/aai/rest/ueb/UEBNotification.java
index be30c468..0c8fde62 100644
--- a/aai-core/src/main/java/org/onap/aai/rest/ueb/UEBNotification.java
+++ b/aai-core/src/main/java/org/onap/aai/rest/ueb/UEBNotification.java
@@ -98,42 +98,15 @@ public class UEBNotification {
Introspector obj, HashMap<String, Introspector> relatedObjects, String basePath)
throws AAIException, UnsupportedEncodingException {
- String action = "UPDATE";
-
- if (status.equals(Status.CREATED)) {
- action = "CREATE";
- } else if (status.equals(Status.OK)) {
- action = "UPDATE";
- } else if (status.equals(Status.NO_CONTENT)) {
- action = "DELETE";
- }
+ String action = getAction(status);
try {
Introspector eventHeader = currentVersionLoader.introspectorFromName("notification-event-header");
URIToObject parser = new URIToObject(currentVersionLoader, uri, relatedObjects);
- if ((basePath != null) && (!basePath.isEmpty())) {
- if (!(basePath.startsWith("/"))) {
- basePath = "/" + basePath;
- }
- if (!(basePath.endsWith("/"))) {
- basePath = basePath + "/";
- }
- } else {
- // default
- basePath = "/aai/";
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Please check the schema.uri.base.path as it didn't seem to be set");
- }
- }
+ basePath = formatBasePath(basePath);
- String uriStr = getUri(uri.toString(), basePath);
- String entityLink;
- if (uriStr.startsWith("/")) {
- entityLink = basePath + notificationVersion + uriStr;
- } else {
- entityLink = basePath + notificationVersion + "/" + uriStr;
- }
+ String entityLink = formatEntityLink(uri, basePath);
eventHeader.setValue("entity-link", entityLink);
eventHeader.setValue("action", action);
@@ -191,6 +164,48 @@ public class UEBNotification {
}
}
+ private String formatEntityLink(URI uri, String basePath) {
+ String uriStr = getUri(uri.toString(), basePath);
+ String entityLink;
+ if (uriStr.startsWith("/")) {
+ entityLink = basePath + notificationVersion + uriStr;
+ } else {
+ entityLink = basePath + notificationVersion + "/" + uriStr;
+ }
+ return entityLink;
+ }
+
+ private String formatBasePath(String basePath) {
+ if ((basePath != null) && (!basePath.isEmpty())) {
+ if (!(basePath.startsWith("/"))) {
+ basePath = "/" + basePath;
+ }
+ if (!(basePath.endsWith("/"))) {
+ basePath = basePath + "/";
+ }
+ } else {
+ // default
+ basePath = "/aai/";
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Please check the schema.uri.base.path as it didn't seem to be set");
+ }
+ }
+ return basePath;
+ }
+
+ private String getAction(Status status) {
+ String action = "UPDATE";
+
+ if (status.equals(Status.CREATED)) {
+ action = "CREATE";
+ } else if (status.equals(Status.OK)) {
+ action = "UPDATE";
+ } else if (status.equals(Status.NO_CONTENT)) {
+ action = "DELETE";
+ }
+ return action;
+ }
+
/**
* Trigger events.
*
diff --git a/aai-core/src/test/java/org/onap/aai/AAISetup.java b/aai-core/src/test/java/org/onap/aai/AAISetup.java
index a44226c8..e1fc351f 100644
--- a/aai-core/src/test/java/org/onap/aai/AAISetup.java
+++ b/aai-core/src/test/java/org/onap/aai/AAISetup.java
@@ -30,6 +30,8 @@ import org.onap.aai.edges.EdgeIngestor;
import org.onap.aai.introspection.LoaderFactory;
import org.onap.aai.introspection.MoxyLoader;
import org.onap.aai.nodes.NodeIngestor;
+import org.onap.aai.prevalidation.ValidationConfiguration;
+import org.onap.aai.prevalidation.ValidationService;
import org.onap.aai.rest.db.HttpEntry;
import org.onap.aai.serialization.db.EdgeSerializer;
import org.onap.aai.serialization.queryformats.QueryFormatTestHelper;
@@ -49,7 +51,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
@ContextConfiguration(
classes = {ConfigConfiguration.class, AAIConfigTranslator.class, EdgeIngestor.class, EdgeSerializer.class,
NodeIngestor.class, SpringContextAware.class, IntrospectionConfig.class, RestBeanConfig.class,
- XmlFormatTransformerConfiguration.class})
+ XmlFormatTransformerConfiguration.class, ValidationService.class, ValidationConfiguration.class})
@TestPropertySource(
properties = {"schema.uri.base.path = /aai", "schema.xsd.maxoccurs = 5000", "schema.translator.list=config",
"schema.nodes.location=src/test/resources/onap/oxm",
diff --git a/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java b/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java
index 371c07a5..59a0f1f1 100644
--- a/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java
+++ b/aai-core/src/test/java/org/onap/aai/rest/db/HttpEntryTest.java
@@ -31,6 +31,8 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -82,6 +84,7 @@ import org.onap.aai.introspection.Introspector;
import org.onap.aai.introspection.Loader;
import org.onap.aai.introspection.ModelType;
import org.onap.aai.parsers.query.QueryParser;
+import org.onap.aai.prevalidation.ValidationService;
import org.onap.aai.rest.db.responses.ErrorResponse;
import org.onap.aai.rest.db.responses.Relationship;
import org.onap.aai.rest.db.responses.RelationshipWrapper;
@@ -93,11 +96,14 @@ import org.onap.aai.serialization.engines.TransactionalGraphEngine;
import org.onap.aai.util.AAIConfig;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
+import org.springframework.boot.test.mock.mockito.MockBean;
@RunWith(value = Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class HttpEntryTest extends AAISetup {
+ @MockBean ValidationService validationService;
+
protected static final MediaType APPLICATION_JSON = MediaType.valueOf("application/json");
private static final Set<Integer> VALID_HTTP_STATUS_CODES = new HashSet<>();
@@ -116,7 +122,7 @@ public class HttpEntryTest extends AAISetup {
*/
@Parameterized.Parameters(name = "QueryStyle.{0}")
public static Collection<Object[]> data() {
- return Arrays.asList(new Object[][] { { QueryStyle.TRAVERSAL }, { QueryStyle.TRAVERSAL_URI } });
+ return Arrays.asList(new Object[][] { { QueryStyle.TRAVERSAL } });
}
private Loader loader;
@@ -196,8 +202,15 @@ public class HttpEntryTest extends AAISetup {
.put("equip-type", "theEquipType")
.toString();
+ JSONObject expectedResponseBody = new JSONObject()
+ .put("hostname", "theHostname")
+ .put("equip-type", "theEquipType");
Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
+ JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
+
+ JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE);
assertEquals("Expected the pserver to be returned", 200, response.getStatus());
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -216,6 +229,7 @@ public class HttpEntryTest extends AAISetup {
Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.PUT, uri, requestBody);
assertEquals("Expecting the pserver to be created", 201, response.getStatus());
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -254,6 +268,7 @@ public class HttpEntryTest extends AAISetup {
assertEquals("Expecting the pserver to be updated", 200, response.getStatus());
assertTrue("That old properties are removed",
traversal.V().has("hostname", "updatedHostname").hasNot("number-of-cpus").hasNext());
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -322,6 +337,7 @@ public class HttpEntryTest extends AAISetup {
traversal.V().has("aai-node-type", "p-interface").has("aai-uri", uri).has("interface-name", "p1")
.out("tosca.relationships.network.BindsTo").has("aai-node-type", "pserver")
.has("hostname", "hostname").hasNext());
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -341,6 +357,7 @@ public class HttpEntryTest extends AAISetup {
assertTrue("object should be updated while keeping old properties",
traversal.V().has("aai-node-type", "pserver").has("hostname", "new-hostname")
.has("equip-type", "the-equip-type").hasNext());
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -357,6 +374,7 @@ public class HttpEntryTest extends AAISetup {
doDelete(resourceVersion, uri, "pserver").getStatus());
assertTrue("Expecting the pserver to be deleted",
!traversal.V().has("aai-node-type", "pserver").has("hostname", "the-hostname").hasNext());
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -406,6 +424,7 @@ public class HttpEntryTest extends AAISetup {
.has(EdgeProperty.PREVENT_DELETE.toString(), "IN");
assertTrue("p-server has incoming edge from complex", vertexQuery.hasNext());
assertTrue("Created Edge has expected properties", edgeQuery.hasNext());
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -524,6 +543,7 @@ public class HttpEntryTest extends AAISetup {
assertEquals("Expected get to succeed", 200, response.getStatus());
assertThat(responseEntity, containsString("/cloud-infrastructure/pservers/pserver/pserver-1"));
assertThat(responseEntity, containsString("/cloud-infrastructure/pservers/pserver/pserver-2"));
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -559,6 +579,7 @@ public class HttpEntryTest extends AAISetup {
assertEquals("Expected the response to be successful", 200, response.getStatus());
assertThat("Related pserver is returned", response.getEntity().toString(),
containsString("\"hostname\":\"related-to-pserver\""));
+ verify(validationService, times(1)).validate(any());
}
@@ -588,6 +609,7 @@ public class HttpEntryTest extends AAISetup {
Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
assertThat("Related to pserver is returned.", response.getEntity().toString(),
containsString("\"hostname\":\"abstract-pserver\""));
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -634,6 +656,7 @@ public class HttpEntryTest extends AAISetup {
relationships[0].getRelatedLink());
assertEquals("complex.physical-location-id", relationships[0].getRelationshipData()[0].getRelationshipKey());
assertEquals("related-to-complex", relationships[0].getRelationshipData()[0].getRelationshipValue());
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -693,6 +716,7 @@ public class HttpEntryTest extends AAISetup {
JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE);
queryParameters.remove("format");
+ verify(validationService, times(1)).validate(any());
}
@Test
@@ -810,4 +834,29 @@ public class HttpEntryTest extends AAISetup {
int depth = traversalHttpEntry.setDepth(null, depthParam);
assertEquals(AAIProperties.MAXIMUM_DEPTH.intValue(), depth);
}
+
+ @Test
+ public void thatEventsAreValidated() throws AAIException, UnsupportedEncodingException {
+ String uri = "/cloud-infrastructure/pservers/pserver/theHostname";
+ traversal.addV()
+ .property("aai-node-type", "pserver")
+ .property("hostname", "theHostname")
+ .property("equip-type", "theEquipType")
+ .property(AAIProperties.AAI_URI, uri)
+ .next();
+ String requestBody = new JSONObject()
+ .put("hostname", "theHostname")
+ .put("equip-type", "theEquipType")
+ .toString();
+
+ JSONObject expectedResponseBody = new JSONObject()
+ .put("hostname", "theHostname")
+ .put("equip-type", "theEquipType");
+ Response response = doRequest(traversalHttpEntry, loader, dbEngine, HttpMethod.GET, uri, requestBody);
+ JSONObject actualResponseBody = new JSONObject(response.getEntity().toString());
+
+ JSONAssert.assertEquals(expectedResponseBody, actualResponseBody, JSONCompareMode.NON_EXTENSIBLE);
+ assertEquals("Expected the pserver to be returned", 200, response.getStatus());
+ verify(validationService, times(1)).validate(any());
+ }
}