aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFiete Ostkamp <Fiete.Ostkamp@telekom.de>2024-06-27 14:12:01 +0200
committerFiete Ostkamp <Fiete.Ostkamp@telekom.de>2024-06-27 19:39:25 +0200
commit05b52a98e26f79d20c9921921d3aebe0f9b49f60 (patch)
treedbeed81c47e6fdd9de72925fc505af91722b8979
parent63cacf6c2333eaaeda3b7f7552c3a85736f9be03 (diff)
Update Janusgraph to 0.5.0 in traversal
- update Janusgraph to 0.5.0 + tinkerpop to 3.4.13 - do not use pagination methods from HttpEntry [1] - introduce WebTestClient as a way to more elegantly declare http requests and assertions [1] pagination is still done on the client-side in this service. This change just removes the usage of methods of HttpEntry that effectively do a List.subList and that will be removed from HttpEntry shortly after Issue-ID: AAI-3902 Change-Id: I446f092048b9e2be7314ed32ab3de5d5e1e1689d Signed-off-by: Fiete Ostkamp <Fiete.Ostkamp@telekom.de>
-rw-r--r--aai-traversal/pom.xml64
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java1
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java10
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java121
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java35
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/dsl/v1/DslListener.java1
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryTestDTO.java10
-rw-r--r--aai-traversal/src/main/java/org/onap/aai/rest/util/PaginationUtil.java54
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/PayloadUtil.java9
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/WebClientConfiguration.java50
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java50
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/GfpVserverDataStoredQueryTest.java6
-rw-r--r--aai-traversal/src/test/java/org/onap/aai/rest/QueryConsumerTest.java59
-rw-r--r--pom.xml6
-rw-r--r--version.properties2
15 files changed, 330 insertions, 148 deletions
diff --git a/aai-traversal/pom.xml b/aai-traversal/pom.xml
index 59527d0..99e5c2d 100644
--- a/aai-traversal/pom.xml
+++ b/aai-traversal/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.onap.aai.traversal</groupId>
<artifactId>traversal</artifactId>
- <version>1.14.2-SNAPSHOT</version>
+ <version>1.14.3-SNAPSHOT</version>
</parent>
<groupId>org.onap.aai.traversal</groupId>
<artifactId>aai-traversal</artifactId>
@@ -94,18 +94,17 @@
<!-- versions -->
<spring.boot.version>2.4.13</spring.boot.version>
- <spring.version>5.3.13</spring.version>
+ <janusgraph.version>0.5.0</janusgraph.version>
+ <gremlin.version>3.4.13</gremlin.version>
+
<spring-cloud.version>2020.0.2</spring-cloud.version>
- <spring.test.version>${spring.version}</spring.test.version>
- <spring.jms.version>${spring.version}</spring.jms.version>
+
<javax.servlet.version>4.0.1</javax.servlet.version>
<antlr.version>4.9.3</antlr.version>
<keycloak.version>11.0.2</keycloak.version>
- <micrometer-spring-legacy.version>1.3.19</micrometer-spring-legacy.version>
- <micrometer-core.version>1.6.6</micrometer-core.version>
- <micrometer-jersey2>1.6.6</micrometer-jersey2>
+
+ <micrometer.version>1.6.6</micrometer.version>
<mockito.core.version>3.4.0</mockito.core.version>
- <powermock.version>2.0.9</powermock.version>
<testcontainers.version>1.6.1</testcontainers.version>
<netty.handler.version>4.1.63.Final</netty.handler.version>
<netty.version>4.1.63.Final</netty.version>
@@ -324,23 +323,18 @@
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
- <artifactId>micrometer-spring-legacy</artifactId>
- <version>${micrometer-spring-legacy.version}</version>
- </dependency>
- <dependency>
- <groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
- <version>${micrometer-core.version}</version>
+ <version>${micrometer.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
- <!-- <version>${micrometer-registry-prometheus.version}</version> -->
+ <version>${micrometer.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-jersey2</artifactId>
- <version>${micrometer-jersey2}</version>
+ <version>${micrometer.version}</version>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
@@ -472,6 +466,11 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>org.janusgraph</groupId>
+ <artifactId>janusgraph-inmemory</artifactId>
+ <version>${janusgraph.version}</version>
+ </dependency>
+ <dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-ffi</artifactId>
</dependency>
@@ -494,34 +493,6 @@
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-module-junit4</artifactId>
- <version>${powermock.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-api-mockito2</artifactId>
- <version>${powermock.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-module-javaagent</artifactId>
- <version>${powermock.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-module-junit4-rule-agent</artifactId>
- <version>${powermock.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.beust</groupId>
- <artifactId>jcommander</artifactId>
- </dependency>
- <dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</dependency>
@@ -682,6 +653,11 @@
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-webflux</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java
index c8f1f0b..6b8382b 100644
--- a/aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2Gremlin.java
@@ -103,7 +103,6 @@ public class CQ2Gremlin extends RESTAPI {
SchemaVersions schemaVersions = SpringContextAware.getBean(SchemaVersions.class);
traversalUriHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion());
- traversalUriHttpEntry.setPaginationParameters("-1", "-1");
TransactionalGraphEngine dbEngine = traversalUriHttpEntry.getDbEngine();
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java
index 8c6477f..bade2cd 100644
--- a/aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/CQ2GremlinTest.java
@@ -66,9 +66,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestBody;
-import com.beust.jcommander.internal.Lists;
-import com.beust.jcommander.internal.Maps;
-
@Path("/cq2gremlintest")
public class CQ2GremlinTest extends RESTAPI {
@@ -106,7 +103,6 @@ public class CQ2GremlinTest extends RESTAPI {
String realTime = headers.getRequestHeaders().getFirst("Real-Time");
SchemaVersions schemaVersions = SpringContextAware.getBean(SchemaVersions.class);
traversalUriHttpEntry.setHttpEntryProperties(schemaVersions.getDefaultVersion());
- traversalUriHttpEntry.setPaginationParameters("-1", "-1");
return processC2UnitTest(content);
}
@@ -159,11 +155,11 @@ public class CQ2GremlinTest extends RESTAPI {
}
private List<Vertex> createGraph(CustomQueryTestDTO content, Graph graph) {
- Map<String, Vertex> verticesMap = Maps.newLinkedHashMap();
+ Map<String, Vertex> verticesMap = new LinkedHashMap<>();
// Creating all the Vertices
content.getVerticesDtos().forEach(vertex -> {
StringBuilder vertexIdentifier = new StringBuilder();
- List<String> keyValues = Lists.newArrayList();
+ List<String> keyValues = new ArrayList<>();
keyValues.add(T.id.toString());
keyValues.add(String.format("%02d", verticesMap.size() * 10));
AtomicInteger index = new AtomicInteger(0);
@@ -199,7 +195,7 @@ public class CQ2GremlinTest extends RESTAPI {
});
- List<Vertex> expectedVertices = Lists.newArrayList();
+ List<Vertex> expectedVertices = new ArrayList<>();
content.getExpectedResultsDtos().getIds()
.forEach(vertexId -> expectedVertices.add(verticesMap.get(vertexId)));
return expectedVertices;
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java b/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java
index 78ca452..8226ddd 100644
--- a/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java
@@ -22,8 +22,6 @@ package org.onap.aai.rest;
import java.io.FileNotFoundException;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -36,10 +34,10 @@ import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.onap.aai.edges.EdgeIngestor;
+import org.javatuples.Pair;
import org.onap.aai.exceptions.AAIException;
-import org.onap.aai.introspection.LoaderFactory;
import org.onap.aai.introspection.ModelType;
+import org.onap.aai.query.builder.Pageable;
import org.onap.aai.rest.db.HttpEntry;
import org.onap.aai.rest.dsl.DslQueryProcessor;
import org.onap.aai.rest.dsl.V1DslQueryProcessor;
@@ -49,6 +47,7 @@ import org.onap.aai.rest.enums.QueryVersion;
import org.onap.aai.rest.search.GenericQueryProcessor;
import org.onap.aai.rest.search.GremlinServerSingleton;
import org.onap.aai.rest.search.QueryProcessorType;
+import org.onap.aai.rest.util.PaginationUtil;
import org.onap.aai.serialization.db.DBSerializer;
import org.onap.aai.serialization.engines.TransactionalGraphEngine;
import org.onap.aai.serialization.queryformats.Format;
@@ -122,19 +121,19 @@ public class DslConsumer extends TraversalConsumer {
@RequestParam(defaultValue = "graphson") String format,
@RequestParam(defaultValue = "no_op") String subgraph,
@RequestParam(defaultValue = "all") String validate,
- @RequestParam(defaultValue = "-1") String resultIndex,
- @RequestParam(defaultValue = "-1") String resultSize,
+ @RequestParam(defaultValue = "-1") int resultIndex,
+ @RequestParam(defaultValue = "-1") int resultSize,
@RequestHeader HttpHeaders headers,
HttpServletRequest request) throws FileNotFoundException, AAIException {
Set<String> roles = this.getRoles(request.getUserPrincipal());
return processExecuteQuery(dslQuery, request, versionParam, format, subgraph,
- validate, headers, resultIndex, resultSize, roles);
+ validate, headers, new Pageable(resultIndex, resultSize), roles);
}
public ResponseEntity<String> processExecuteQuery(String dslQuery, HttpServletRequest request, String versionParam,
String queryFormat, String subgraph, String validate, HttpHeaders headers,
- String resultIndex, String resultSize, Set<String> roles) throws FileNotFoundException, AAIException {
+ Pageable pageable, Set<String> roles) throws FileNotFoundException, AAIException {
final SchemaVersion version = new SchemaVersion(versionParam);
final String sourceOfTruth = headers.getFirst("X-FromAppId");
@@ -151,8 +150,49 @@ public class DslConsumer extends TraversalConsumer {
}
}
- String result = executeQuery(dslQuery, request, queryFormat, subgraph, validate, queryParams, resultIndex, resultSize,
+ Pair<List<Object>,Map<String,List<String>>> executionResult = executeQuery(dslQuery, request, queryFormat, subgraph, validate, queryParams, pageable,
roles, version, sourceOfTruth, dslOverride);
+ List<Object> vertices = executionResult.getValue0();
+
+ String result = serializeResponse(request, queryFormat, headers, version, sourceOfTruth, queryParams, executionResult.getValue1(), vertices);
+
+ if (PaginationUtil.hasValidPaginationParams(pageable)) {
+ int totalCount = vertices.size();
+ long totalPages = PaginationUtil.getTotalPages(pageable, totalCount);
+ return ResponseEntity.ok()
+ .header("total-results", String.valueOf(totalCount))
+ .header("total-pages", String.valueOf(totalPages))
+ .body(result);
+ } else {
+ return ResponseEntity.ok(result);
+ }
+ }
+
+ private String serializeResponse(HttpServletRequest request, String queryFormat, HttpHeaders headers,
+ final SchemaVersion version, final String sourceOfTruth, MultivaluedMap<String, String> queryParameters, final Map<String, List<String>> propertiesMap,
+ List<Object> vertices) throws AAIException {
+ DBSerializer serializer =
+ new DBSerializer(version, httpEntry.getDbEngine(), ModelType.MOXY, sourceOfTruth);
+ String serverBase = request.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/");
+ FormatFactory ff = new FormatFactory(httpEntry.getLoader(), serializer,
+ schemaVersions, this.basePath, serverBase);
+
+ MultivaluedMap<String, String> mvm = new MultivaluedHashMap<>();
+ mvm.putAll(queryParameters);
+ Format format = Format.getFormat(queryFormat);
+ if (isHistory(format)) {
+ mvm.putSingle("startTs", Long.toString(getStartTime(format, mvm)));
+ mvm.putSingle("endTs", Long.toString(getEndTime(mvm)));
+ }
+ Formatter formatter = ff.get(format, mvm);
+
+ String result = "";
+ if (propertiesMap != null && !propertiesMap.isEmpty()) {
+ result = formatter.output(vertices, propertiesMap).toString();
+ } else {
+ result = formatter.output(vertices).toString();
+ }
+
MediaType acceptType = headers.getAccept().stream()
.filter(Objects::nonNull)
.filter(header -> !header.equals(MediaType.ALL))
@@ -162,25 +202,16 @@ public class DslConsumer extends TraversalConsumer {
if (MediaType.APPLICATION_XML.isCompatibleWith(acceptType)) {
result = xmlFormatTransformer.transform(result);
}
-
- if (httpEntry.isPaginated()) {
- return ResponseEntity.ok()
- .header("total-results", String.valueOf(httpEntry.getTotalVertices()))
- .header("total-pages", String.valueOf(httpEntry.getTotalPaginationBuckets()))
- .body(result);
- } else {
- return ResponseEntity.ok(result);
- }
+ return result;
}
- private String executeQuery(String content, HttpServletRequest req, String queryFormat, String subgraph,
- String validate, MultivaluedMap<String, String> queryParameters, String resultIndex, String resultSize, Set<String> roles,
+ private Pair<List<Object>,Map<String,List<String>>> executeQuery(String content, HttpServletRequest req, String queryFormat, String subgraph,
+ String validate, MultivaluedMap<String, String> queryParameters, Pageable pageable, Set<String> roles,
final SchemaVersion version, final String sourceOfTruth, final String dslOverride)
throws AAIException, FileNotFoundException {
final String serverBase =
req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/");
httpEntry.setHttpEntryProperties(version, serverBase);
- httpEntry.setPaginationParameters(resultIndex, resultSize);
JsonObject input = JsonParser.parseString(content).getAsJsonObject();
JsonElement dslElement = input.get("dsl");
@@ -215,7 +246,7 @@ public class DslConsumer extends TraversalConsumer {
final TransactionalGraphEngine dbEngine = httpEntry.getDbEngine();
GraphTraversalSource traversalSource =
getTraversalSource(dbEngine, format, queryParameters, roles);
-
+
GenericQueryProcessor processor =
new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton)
.queryFrom(dsl, "dsl").queryProcessor(dslQueryProcessor).version(dslApiVersion)
@@ -229,34 +260,18 @@ public class DslConsumer extends TraversalConsumer {
if (isAggregate(format)) {
// Dedup if duplicate objects are returned in each array in the aggregate format
// scenario.
- List<Object> vertTempDedupedObjectList = dedupObjectInAggregateFormatResult(vertTemp);
- vertices = httpEntry
- .getPaginatedVertexListForAggregateFormat(vertTempDedupedObjectList);
+ List<Object> vertTempDedupedObjectList = dedupObjectInAggregateFormatResultStreams(vertTemp);
+ vertices = PaginationUtil.hasValidPaginationParams(pageable)
+ ? vertices = PaginationUtil.getPaginatedVertexListForAggregateFormat(vertTempDedupedObjectList, pageable)
+ : vertTempDedupedObjectList;
} else {
- vertices = httpEntry.getPaginatedVertexList(vertTemp);
+ int startIndex = pageable.getPage() * pageable.getPageSize();
+ vertices = PaginationUtil.hasValidPaginationParams(pageable)
+ ? vertTemp.subList(startIndex, startIndex + pageable.getPageSize())
+ : vertTemp;
}
- DBSerializer serializer =
- new DBSerializer(version, dbEngine, ModelType.MOXY, sourceOfTruth);
- FormatFactory ff = new FormatFactory(httpEntry.getLoader(), serializer,
- schemaVersions, this.basePath, serverBase);
-
- MultivaluedMap<String, String> mvm = new MultivaluedHashMap<>();
- mvm.putAll(queryParameters);
- if (isHistory(format)) {
- mvm.putSingle("startTs", Long.toString(getStartTime(format, mvm)));
- mvm.putSingle("endTs", Long.toString(getEndTime(mvm)));
- }
- Formatter formatter = ff.get(format, mvm);
-
- final Map<String, List<String>> propertiesMap = processor.getPropertiesMap();
- String result = "";
- if (propertiesMap != null && !propertiesMap.isEmpty()) {
- result = formatter.output(vertices, propertiesMap).toString();
- } else {
- result = formatter.output(vertices).toString();
- }
- return result;
+ return Pair.with(vertices, processor.getPropertiesMap());
}
private List<Object> dedupObjectInAggregateFormatResultStreams(List<Object> vertTemp) {
@@ -265,18 +280,6 @@ public class DslConsumer extends TraversalConsumer {
.map(o -> ((ArrayList<?>) o).stream().distinct().collect(Collectors.toList()))
.collect(Collectors.toList());
}
- private List<Object> dedupObjectInAggregateFormatResult(List<Object> vertTemp) {
- List<Object> vertTempDedupedObjectList = new ArrayList<Object>();
- Iterator<Object> itr = vertTemp.listIterator();
- while (itr.hasNext()) {
- Object o = itr.next();
- if (o instanceof ArrayList) {
- vertTempDedupedObjectList
- .add(((ArrayList) o).stream().distinct().collect(Collectors.toList()));
- }
- }
- return vertTempDedupedObjectList;
- }
private MultivaluedMap<String, String> toMultivaluedMap(Map<String, String[]> map) {
MultivaluedMap<String, String> multivaluedMap = new MultivaluedHashMap<>();
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java b/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java
index 5a2e19f..5aad81e 100644
--- a/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java
@@ -51,11 +51,13 @@ import org.onap.aai.exceptions.AAIException;
import org.onap.aai.introspection.ModelType;
import org.onap.aai.logging.ErrorLogHelper;
import org.onap.aai.parsers.query.QueryParser;
+import org.onap.aai.query.builder.Pageable;
import org.onap.aai.rest.db.HttpEntry;
import org.onap.aai.rest.search.CustomQueryConfig;
import org.onap.aai.rest.search.GenericQueryProcessor;
import org.onap.aai.rest.search.GremlinServerSingleton;
import org.onap.aai.rest.search.QueryProcessorType;
+import org.onap.aai.rest.util.PaginationUtil;
import org.onap.aai.restcore.HttpMethod;
import org.onap.aai.restcore.util.URITools;
import org.onap.aai.serialization.db.DBSerializer;
@@ -80,8 +82,8 @@ import com.google.gson.JsonParser;
import io.micrometer.core.annotation.Timed;
-@Path("{version: v[1-9][0-9]*|latest}/query")
@Timed
+@Path("{version: v[1-9][0-9]*|latest}/query")
public class QueryConsumer extends TraversalConsumer {
private QueryProcessorType processorType = QueryProcessorType.LOCAL_GROOVY;
@@ -112,12 +114,16 @@ public class QueryConsumer extends TraversalConsumer {
@PUT
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
- public Response executeQuery(String content, @PathParam("version") String versionParam,
+ public Response executeQuery(
+ String content,
+ @PathParam("version") String versionParam,
@DefaultValue("graphson") @QueryParam("format") String queryFormat,
@DefaultValue("no_op") @QueryParam("subgraph") String subgraph,
- @Context HttpHeaders headers, @Context HttpServletRequest req, @Context UriInfo info,
- @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex,
- @DefaultValue("-1") @QueryParam("resultSize") String resultSize) {
+ @DefaultValue("-1") @QueryParam("resultIndex") int resultIndex,
+ @DefaultValue("-1") @QueryParam("resultSize") int resultSize,
+ @Context HttpHeaders headers,
+ @Context HttpServletRequest req,
+ @Context UriInfo info) {
Set<String> roles = this.getRoles(req.getUserPrincipal());
return runner(TraversalConstants.AAI_TRAVERSAL_TIMEOUT_ENABLED,
@@ -127,14 +133,13 @@ public class QueryConsumer extends TraversalConsumer {
@Override
public Response process() {
return processExecuteQuery(content, req, versionParam, queryFormat, subgraph,
- headers, info, resultIndex, resultSize, roles);
+ headers, info, new Pageable(resultIndex, resultSize), roles);
}
});
}
public Response processExecuteQuery(String content, HttpServletRequest req, String versionParam,
- String queryFormat, String subgraph, HttpHeaders headers, UriInfo info, String resultIndex,
- String resultSize, Set<String> roles) {
+ String queryFormat, String subgraph, HttpHeaders headers, UriInfo info, Pageable pageable, Set<String> roles) {
String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
String queryProcessor = headers.getRequestHeaders().getFirst("QueryProcessor");
@@ -166,7 +171,6 @@ public class QueryConsumer extends TraversalConsumer {
* Changes for Pagination
*/
- traversalUriHttpEntry.setPaginationParameters(resultIndex, resultSize);
dbEngine = traversalUriHttpEntry.getDbEngine();
if (startElement != null) {
@@ -243,7 +247,10 @@ public class QueryConsumer extends TraversalConsumer {
.traversalSource(isHistory(format), traversalSource).create();
}
List<Object> vertTemp = processor.execute(subGraphStyle);
- List<Object> vertices = traversalUriHttpEntry.getPaginatedVertexList(vertTemp);
+ int fromIndex = pageable.getPage() * pageable.getPageSize();
+ List<Object> vertices = PaginationUtil.hasValidPaginationParams(pageable)
+ ? vertTemp.subList(fromIndex, fromIndex + pageable.getPageSize())
+ : vertTemp;
DBSerializer serializer =
new DBSerializer(version, dbEngine, ModelType.MOXY, sourceOfTruth);
@@ -270,10 +277,12 @@ public class QueryConsumer extends TraversalConsumer {
result = xmlFormatTransformer.transform(result);
}
- if (traversalUriHttpEntry.isPaginated()) {
+ if (PaginationUtil.hasValidPaginationParams(pageable)) {
+ int totalCount = vertTemp.size();
+ long totalPages = PaginationUtil.getTotalPages(pageable, totalCount);
response = Response.status(Status.OK).type(acceptType)
- .header("total-results", traversalUriHttpEntry.getTotalVertices())
- .header("total-pages", traversalUriHttpEntry.getTotalPaginationBuckets())
+ .header("total-results", totalCount)
+ .header("total-pages", totalPages)
.entity(result).build();
} else {
response = Response.status(Status.OK).type(acceptType).entity(result).build();
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v1/DslListener.java b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v1/DslListener.java
index 1ad1292..ce326df 100644
--- a/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v1/DslListener.java
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/dsl/v1/DslListener.java
@@ -40,7 +40,6 @@ import org.onap.aai.setup.SchemaVersions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
-import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
/**
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryTestDTO.java b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryTestDTO.java
index b64f07f..5c2129a 100644
--- a/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryTestDTO.java
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/search/CustomQueryTestDTO.java
@@ -28,9 +28,9 @@ package org.onap.aai.rest.search;
* 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.
@@ -39,9 +39,9 @@ package org.onap.aai.rest.search;
* ============LICENSE_END=========================================================
*/
-import com.beust.jcommander.internal.Maps;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -58,10 +58,10 @@ public class CustomQueryTestDTO {
private List<LinkedHashMap<String, String>> edgesDtos;
@JsonProperty("optional-properties")
- private Map<String, String> queryOptionalProperties = Maps.newHashMap();
+ private Map<String, String> queryOptionalProperties = new HashMap<>();
@JsonProperty("required-properties")
- private Map<String, String> queryRequiredProperties = Maps.newHashMap();
+ private Map<String, String> queryRequiredProperties = new HashMap<>();
@JsonProperty("expected-result")
private ExpectedResultsDto expectedResultsDtos;
diff --git a/aai-traversal/src/main/java/org/onap/aai/rest/util/PaginationUtil.java b/aai-traversal/src/main/java/org/onap/aai/rest/util/PaginationUtil.java
new file mode 100644
index 0000000..5e8c567
--- /dev/null
+++ b/aai-traversal/src/main/java/org/onap/aai/rest/util/PaginationUtil.java
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2024 Deutsche Telekom. 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.aai.rest.util;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.onap.aai.exceptions.AAIException;
+import org.onap.aai.query.builder.Pageable;
+
+public class PaginationUtil {
+
+ public static List<Object> getPaginatedVertexListForAggregateFormat(List<Object> aggregateVertexList, Pageable pageable) throws AAIException {
+ if (aggregateVertexList != null && !aggregateVertexList.isEmpty() && aggregateVertexList.size() == 1) {
+ List<Object> vertexList = (List<Object>) aggregateVertexList.get(0);
+ int fromIndex = pageable.getPage() * pageable.getPageSize();
+ List<Object> page = vertexList.subList(fromIndex, fromIndex + pageable.getPageSize());
+ return Collections.singletonList(page);
+ }
+ // If the list size is greater than 1 or if pagination is not needed, return the original list.
+ return aggregateVertexList;
+ }
+
+ public static boolean hasValidPaginationParams(Pageable pageable) {
+ return pageable.getPage() >= 0 && pageable.getPageSize() > 0;
+ }
+
+ public static long getTotalPages(Pageable pageable, long totalCount) {
+ int pageSize = pageable.getPageSize();
+ long totalPages = totalCount / pageSize;
+ // conditionally add a page for the remainder
+ if (totalCount % pageSize > 0) {
+ totalPages++;
+ }
+ return totalPages;
+ }
+}
diff --git a/aai-traversal/src/test/java/org/onap/aai/PayloadUtil.java b/aai-traversal/src/test/java/org/onap/aai/PayloadUtil.java
index 5a86d92..75ecb1f 100644
--- a/aai-traversal/src/test/java/org/onap/aai/PayloadUtil.java
+++ b/aai-traversal/src/test/java/org/onap/aai/PayloadUtil.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
@@ -43,7 +44,7 @@ public class PayloadUtil {
String message = String.format("Unable to find the %s in src/test/resources", fileName);
assertNotNull(message, inputStream);
- String resource = IOUtils.toString(inputStream);
+ String resource = IOUtils.toString(inputStream, Charset.defaultCharset());
inputStream.close();
return resource;
@@ -57,7 +58,7 @@ public class PayloadUtil {
String message = String.format("Unable to find the %s in src/test/resources", fileName);
assertNotNull(message, inputStream);
- String resource = IOUtils.toString(inputStream);
+ String resource = IOUtils.toString(inputStream, Charset.defaultCharset());
inputStream.close();
return resource;
@@ -77,7 +78,7 @@ public class PayloadUtil {
if (cache.containsKey(fileName)) {
resource = cache.get(fileName);
} else {
- resource = IOUtils.toString(inputStream);
+ resource = IOUtils.toString(inputStream, Charset.defaultCharset());
cache.put(fileName, resource);
}
@@ -112,7 +113,7 @@ public class PayloadUtil {
.format("Unable to find the %s in src/test/resources/payloads/named-queries", fileName);
assertNotNull(message, inputStream);
- String resource = IOUtils.toString(inputStream);
+ String resource = IOUtils.toString(inputStream, Charset.defaultCharset());
inputStream.close();
return resource;
diff --git a/aai-traversal/src/test/java/org/onap/aai/WebClientConfiguration.java b/aai-traversal/src/test/java/org/onap/aai/WebClientConfiguration.java
new file mode 100644
index 0000000..73239c6
--- /dev/null
+++ b/aai-traversal/src/test/java/org/onap/aai/WebClientConfiguration.java
@@ -0,0 +1,50 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2024 Deutsche Telekom. 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.aai;
+
+import java.time.Duration;
+import java.util.Collections;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.reactive.server.WebTestClient;
+
+@TestConfiguration
+public class WebClientConfiguration {
+
+ @Lazy
+ @Bean
+ WebTestClient webTestClient(@LocalServerPort int port) {
+ return WebTestClient.bindToServer()
+ .baseUrl("http://localhost:" + port)
+ .responseTimeout(Duration.ofSeconds(300))
+ .defaultHeaders(headers -> {
+ headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
+ headers.set("Real-Time", "true");
+ headers.set("X-FromAppId", "JUNIT");
+ headers.set("X-TransactionId", "JUNIT");
+ headers.setBasicAuth("AAI", "AAI");
+ })
+ .build();
+ }
+}
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java
index a4fb0a7..ed4a6e6 100644
--- a/aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java
@@ -29,11 +29,9 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
@@ -42,6 +40,7 @@ import org.janusgraph.core.JanusGraphTransaction;
import org.junit.Assert;
import org.junit.Test;
import org.onap.aai.PayloadUtil;
+import org.onap.aai.WebClientConfiguration;
import org.onap.aai.dbmap.AAIGraph;
import org.onap.aai.entities.AAIErrorResponse;
import org.onap.aai.entities.ServiceException;
@@ -49,23 +48,26 @@ import org.onap.aai.util.AAIConfig;
import org.onap.aai.util.TraversalConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Import;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
+import org.springframework.test.web.reactive.server.WebTestClient;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
+@Import(WebClientConfiguration.class)
public class DslConsumerTest extends AbstractSpringRestTest {
private static final Logger LOGGER = LoggerFactory.getLogger(DslConsumerTest.class);
- private static final ObjectMapper objectMapper = new ObjectMapper();
+ @Autowired WebTestClient webClient;
@Override
public void createTestGraph() {
@@ -208,6 +210,46 @@ public class DslConsumerTest extends AbstractSpringRestTest {
}
@Test
+ public void thatResultsCanBePaginated() throws Exception {
+ String path = "/aai/v14/dsl";
+ Map<String, String> dslQueryMap = Collections.singletonMap("dsl-query", "pserver*('hostname','test-pserver-dsl')");
+
+ String payload = PayloadUtil.getTemplatePayload("dsl-query.json", dslQueryMap);
+
+ webClient.put()
+ .uri(uriBuilder -> uriBuilder
+ .path(path)
+ .queryParam("format", "console")
+ .build())
+ .contentType(MediaType.APPLICATION_JSON)
+ .bodyValue(payload)
+ .exchange()
+ .expectStatus().isOk();
+
+ String responseEntity = webClient.put()
+ .uri(uriBuilder -> uriBuilder
+ .path(path)
+ .queryParam("format", "console")
+ .queryParam("resultIndex", 0)
+ .queryParam("resultSize", 1)
+ .build())
+ .contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.APPLICATION_XML)
+ .bodyValue(payload)
+ .exchange()
+ .expectStatus().isOk()
+ .expectHeader().valueEquals("total-results", 1)
+ .expectHeader().valueEquals("total-pages", 1)
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ assertThat(responseEntity,
+ is(not(containsString("<result><result>"))));
+ assertThat(responseEntity, is(containsString("<results><result>")));
+ }
+
+ @Test
public void thatWildcardContentTypeCanBeUsed() throws Exception {
String endpoint = "/aai/v14/dsl?format=console";
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/GfpVserverDataStoredQueryTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/GfpVserverDataStoredQueryTest.java
index f305e14..f43c91f 100644
--- a/aai-traversal/src/test/java/org/onap/aai/rest/GfpVserverDataStoredQueryTest.java
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/GfpVserverDataStoredQueryTest.java
@@ -182,7 +182,7 @@ public class GfpVserverDataStoredQueryTest extends AAISetup {
.thenReturn(new StringBuffer("https://localhost:8446" + query));
Response response = queryConsumer.executeQuery(payload, version.toString(),
- "resource_and_url", "" + "no_op", httpHeaders, mockRequest, uriInfo, "-1", "-1");
+ "resource_and_url", "" + "no_op", -1, -1, httpHeaders, mockRequest, uriInfo);
String entity = response.getEntity().toString();
assertEquals("Expected the response to be 200 but got this returned: "
@@ -214,7 +214,7 @@ public class GfpVserverDataStoredQueryTest extends AAISetup {
.thenReturn(new StringBuffer("https://localhost:8446" + query));
Response response = queryConsumer.executeQuery(payload, version.toString(),
- "resource_and_url", "" + "no_op", httpHeaders, mockRequest, uriInfo, "-1", "-1");
+ "resource_and_url", "" + "no_op", -1, -1, httpHeaders, mockRequest, uriInfo);
String entity = response.getEntity().toString();
@@ -247,7 +247,7 @@ public class GfpVserverDataStoredQueryTest extends AAISetup {
.thenReturn(new StringBuffer("https://localhost:8446" + query));
Response response = queryConsumer.executeQuery(payload, version.toString(),
- "resource_and_url", "" + "no_op", httpHeaders, mockRequest, uriInfo, "-1", "-1");
+ "resource_and_url", "" + "no_op", -1, -1, httpHeaders, mockRequest, uriInfo);
String entity = response.getEntity().toString();
diff --git a/aai-traversal/src/test/java/org/onap/aai/rest/QueryConsumerTest.java b/aai-traversal/src/test/java/org/onap/aai/rest/QueryConsumerTest.java
index cfb81d4..a6da4fc 100644
--- a/aai-traversal/src/test/java/org/onap/aai/rest/QueryConsumerTest.java
+++ b/aai-traversal/src/test/java/org/onap/aai/rest/QueryConsumerTest.java
@@ -42,6 +42,7 @@ import org.onap.aai.HttpTestUtil;
import org.onap.aai.PayloadUtil;
import org.onap.aai.TraversalApp;
import org.onap.aai.TraversalTestConfiguration;
+import org.onap.aai.WebClientConfiguration;
import org.onap.aai.config.PropertyPasswordConfiguration;
import org.onap.aai.dbmap.AAIGraph;
import org.onap.aai.exceptions.AAIException;
@@ -55,6 +56,7 @@ import org.springframework.http.*;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.client.RestTemplate;
@RunWith(SpringRunner.class)
@@ -63,7 +65,7 @@ import org.springframework.web.client.RestTemplate;
classes = TraversalApp.class)
@TestPropertySource(locations = "classpath:application-test.properties")
@ContextConfiguration(initializers = PropertyPasswordConfiguration.class)
-@Import(TraversalTestConfiguration.class)
+@Import({TraversalTestConfiguration.class, WebClientConfiguration.class})
public class QueryConsumerTest {
private static final Logger LOGGER = LoggerFactory.getLogger(QueryConsumerTest.class);
@@ -71,6 +73,8 @@ public class QueryConsumerTest {
private String pserverUri;
+ @Autowired WebTestClient webTestClient;
+
@Autowired
RestTemplate restTemplate;
@@ -124,7 +128,7 @@ public class QueryConsumerTest {
Response response = httpTestUtil.doPut(complexUri, complexPayload);
}
- // @Test
+ @Test
public void testRequiredAGood() throws Exception {
String endpoint = "/aai/v14/query?format=pathed";
Map<String, String> cloudRegionMap = new HashMap<>();
@@ -152,7 +156,7 @@ public class QueryConsumerTest {
String payload = PayloadUtil.getTemplatePayload("custom-query.json", customQueryMap);
httpEntity = new HttpEntity(payload, headers);
- ResponseEntity responseEntity =
+ ResponseEntity<String> responseEntity =
restTemplate.exchange(baseUrl + endpoint, HttpMethod.PUT, httpEntity, String.class);
LOGGER.info("Response of custom query : {}", responseEntity.getBody().toString());
assertThat(responseEntity.getStatusCode(), is(HttpStatus.OK));
@@ -162,6 +166,55 @@ public class QueryConsumerTest {
}
@Test
+ public void thatPaginatedResponseCanBeRetrieved() throws Exception {
+ Map<String, String> cloudRegionMap = new HashMap<>();
+ cloudRegionMap.put("cloud-owner", "test-owner-id1111");
+ cloudRegionMap.put("cloud-region-id", "test-region-id1111");
+ cloudRegionMap.put("tenant-id", "test-tenant-id1111");
+ cloudRegionMap.put("tenant-name", "test-tenant-name-id1111");
+ cloudRegionMap.put("vserver-id", "some-vserver-id-id1111");
+ cloudRegionMap.put("vserver-name", "test-vserver-name-id1111");
+ cloudRegionMap.put("pserver-uri", pserverUri);
+ cloudRegionUri =
+ "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/test-owner-id1111/test-region-id1111";
+ addCloudRegion(cloudRegionMap, cloudRegionUri);
+
+ Map<String, String> complexMap = new HashMap<>();
+ complexMap.put("physical-location-id", "location-1111");
+ complexMap.put("cloud-region-uri", cloudRegionUri);
+ String complexUri = "/aai/v14/cloud-infrastructure/complexes/complex/location-1111";
+ addComplex(complexMap, complexUri);
+
+ Map<String, String> customQueryMap = new HashMap<>();
+ customQueryMap.put("start", "cloud-infrastructure/cloud-regions");
+ customQueryMap.put("query", "cloud-region-sites?owner=test-owner-id1111");
+
+ String payload = PayloadUtil.getTemplatePayload("custom-query.json", customQueryMap);
+ String path = "/aai/v14/query";
+
+ String response = webTestClient.put()
+ .uri(uriBuilder -> uriBuilder
+ .path(path)
+ .queryParam("format", "pathed")
+ .queryParam("resultIndex", 0)
+ .queryParam("resultSize", 1)
+ .build())
+ .contentType(MediaType.APPLICATION_JSON)
+ .bodyValue(payload)
+ .exchange()
+ .expectStatus().isOk()
+ .expectHeader().valueEquals("total-results", 2)
+ .expectHeader().valueEquals("total-pages", 2)
+ .returnResult(String.class)
+ .getResponseBody()
+ .blockFirst();
+
+ String expectedResponse = "{\"results\":[{\"resource-type\":\"cloud-region\",\"resource-link\":\"/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/test-owner-id1111/test-region-id1111\"}]}";
+ assertEquals(expectedResponse, response);
+
+ }
+
+ @Test
public void testRequiredBad() throws Exception {
String endpoint = "/aai/v14/query?format=pathed";
Map<String, String> cloudRegionMap = new HashMap<>();
diff --git a/pom.xml b/pom.xml
index 6643722..6ac42c4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,11 +26,11 @@
<parent>
<groupId>org.onap.aai.aai-common</groupId>
<artifactId>aai-parent</artifactId>
- <version>1.14.2-SNAPSHOT</version>
+ <version>1.14.3-SNAPSHOT</version>
</parent>
<groupId>org.onap.aai.traversal</groupId>
<artifactId>traversal</artifactId>
- <version>1.14.2-SNAPSHOT</version>
+ <version>1.14.3-SNAPSHOT</version>
<name>aai-traversal</name>
<packaging>pom</packaging>
<modules>
@@ -41,7 +41,7 @@
Nexus Proxy Properties and Snapshot Locations
Ideally this can be overwritten at runtime per internal environment specific values at runtime
-->
- <aai.common.version>1.14.2</aai.common.version>
+ <aai.common.version>1.14.3-SNAPSHOT</aai.common.version>
<nexusproxy>https://nexus.onap.org</nexusproxy>
<site.path>/content/sites/site/org/onap/aai/traversal/${project.artifactId}/${project.version}</site.path>
<release.path>/content/repositories/releases/</release.path>
diff --git a/version.properties b/version.properties
index 466ec95..a9c3f22 100644
--- a/version.properties
+++ b/version.properties
@@ -5,7 +5,7 @@
major_version=1
minor_version=14
-patch_version=2
+patch_version=3
base_version=${major_version}.${minor_version}.${patch_version}