Separate entity retrieval from jax-rs Response creation 70/136770/2
authorFiete Ostkamp <Fiete.Ostkamp@telekom.de>
Fri, 8 Dec 2023 15:47:19 +0000 (16:47 +0100)
committerFiete Ostkamp <fiete.ostkamp@telekom.de>
Fri, 8 Dec 2023 16:01:39 +0000 (16:01 +0000)
- move logic to retrieve entity from db into a separate method
- do not use runner() from AAI core [1][2]
- use global ExceptionHandler to provide a common exception to error response mapping

[1] the runner will spawn a separate thread to process the request. In this change there is nothing to replace this functionality.
The reason that it is removed is that it tightly couples the app with a) aai-common and b) jax-rs and is also catching all exceptions.
Also the timeout mechanism that is implemented is not actually stopping the execution of the thread after the timeout, but rather returning an early response (after 3 minutes(!)).
[2] these changes are also done to make a future full migration to spring boot/the removal of jax-rs easier
Issue-ID: AAI-3693
Change-Id: I177913c5f6295e1cab476e3c206fecacd7620f69
Signed-off-by: Fiete Ostkamp <Fiete.Ostkamp@telekom.de>
aai-traversal/pom.xml
aai-traversal/src/main/java/org/onap/aai/entities/AAIErrorResponse.java [new file with mode: 0644]
aai-traversal/src/main/java/org/onap/aai/entities/RequestError.java [new file with mode: 0644]
aai-traversal/src/main/java/org/onap/aai/entities/ServiceException.java [new file with mode: 0644]
aai-traversal/src/main/java/org/onap/aai/rest/DslConsumer.java
aai-traversal/src/main/java/org/onap/aai/rest/ExceptionHandler.java
aai-traversal/src/main/java/org/onap/aai/rest/QueryConsumer.java
aai-traversal/src/main/java/org/onap/aai/rest/TraversalConsumer.java
aai-traversal/src/main/java/org/onap/aai/web/JerseyConfiguration.java
aai-traversal/src/test/java/org/onap/aai/rest/DslConsumerTest.java
aai-traversal/src/test/java/org/onap/aai/rest/ExceptionHandlerTest.java

index c079cf4..e8a7916 100644 (file)
                        <version>${keycloak.version}</version>
                        <scope>test</scope>
                </dependency>
+               <dependency>
+                       <groupId>org.projectlombok</groupId>
+                       <artifactId>lombok</artifactId>
+                       <version>1.18.30</version>
+                       <scope>provided</scope>
+               </dependency>
        </dependencies>
        <dependencyManagement>
                <dependencies>
diff --git a/aai-traversal/src/main/java/org/onap/aai/entities/AAIErrorResponse.java b/aai-traversal/src/main/java/org/onap/aai/entities/AAIErrorResponse.java
new file mode 100644 (file)
index 0000000..b80b83d
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2023 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.entities;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class AAIErrorResponse {
+    private RequestError requestError;
+}
diff --git a/aai-traversal/src/main/java/org/onap/aai/entities/RequestError.java b/aai-traversal/src/main/java/org/onap/aai/entities/RequestError.java
new file mode 100644 (file)
index 0000000..4aaf43c
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2023 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.entities;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class RequestError {
+    private ServiceException serviceException;
+}
diff --git a/aai-traversal/src/main/java/org/onap/aai/entities/ServiceException.java b/aai-traversal/src/main/java/org/onap/aai/entities/ServiceException.java
new file mode 100644 (file)
index 0000000..3eb9a21
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2023 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.entities;
+
+import java.util.List;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class ServiceException {
+    private String messageId;
+    private String text;
+    private List<String> variables;
+}
index bbb1aea..d814b48 100644 (file)
@@ -3,6 +3,7 @@
  * org.onap.aai
  * ================================================================================
  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 Deutsche Telekom SA.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +20,7 @@
  */
 package org.onap.aai.rest;
 
+import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -78,33 +80,28 @@ import com.google.gson.JsonParser;
 
 import io.micrometer.core.annotation.Timed;
 
-@Path("{version: v[1-9][0-9]*|latest}/dsl")
 @Timed
+@Path("{version: v[1-9][0-9]*|latest}/dsl")
 public class DslConsumer extends TraversalConsumer {
 
-    private HttpEntry traversalUriHttpEntry;
-
-    private QueryProcessorType processorType = QueryProcessorType.LOCAL_GROOVY;
-
     private static final Logger LOGGER = LoggerFactory.getLogger(DslConsumer.class);
+    private static final QueryProcessorType processorType = QueryProcessorType.LOCAL_GROOVY;
+    private static final QueryVersion DEFAULT_VERSION = QueryVersion.V1;
 
-    private DslQueryProcessor dslQueryProcessor;
-
-    private SchemaVersions schemaVersions;
-
-    private String basePath;
+    private final HttpEntry traversalUriHttpEntry;
+    private final DslQueryProcessor dslQueryProcessor;
+    private final SchemaVersions schemaVersions;
+    private final String basePath;
+    private final GremlinServerSingleton gremlinServerSingleton;
+    private final XmlFormatTransformer xmlFormatTransformer;
 
-    private GremlinServerSingleton gremlinServerSingleton;
-    private final QueryVersion DEFAULT_VERSION = QueryVersion.V1;
     private QueryVersion dslApiVersion = DEFAULT_VERSION;
 
-    private XmlFormatTransformer xmlFormatTransformer;
-
     @Autowired
     public DslConsumer(HttpEntry traversalUriHttpEntry, DslQueryProcessor dslQueryProcessor,
-        SchemaVersions schemaVersions, GremlinServerSingleton gremlinServerSingleton,
-        XmlFormatTransformer xmlFormatTransformer,
-        @Value("${schema.uri.base.path}") String basePath) {
+            SchemaVersions schemaVersions, GremlinServerSingleton gremlinServerSingleton,
+            XmlFormatTransformer xmlFormatTransformer,
+            @Value("${schema.uri.base.path}") String basePath) {
         this.traversalUriHttpEntry = traversalUriHttpEntry;
         this.dslQueryProcessor = dslQueryProcessor;
         this.schemaVersions = schemaVersions;
@@ -116,33 +113,28 @@ public class DslConsumer extends TraversalConsumer {
     @PUT
     @Consumes({MediaType.APPLICATION_JSON})
     @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
-    public Response executeQuery(String content, @PathParam("version") String versionParam,
-        @DefaultValue("graphson") @QueryParam("format") String queryFormat,
-        @DefaultValue("no_op") @QueryParam("subgraph") String subgraph,
-        @DefaultValue("all") @QueryParam("validate") String validate, @Context HttpHeaders headers,
-        @Context HttpServletRequest req, @Context UriInfo info,
-        @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex,
-        @DefaultValue("-1") @QueryParam("resultSize") String resultSize) {
+    public Response executeQuery(String dslQuery, @PathParam("version") String versionParam,
+            @DefaultValue("graphson") @QueryParam("format") String queryFormat,
+            @DefaultValue("no_op") @QueryParam("subgraph") String subgraph,
+            @DefaultValue("all") @QueryParam("validate") String validate,
+            @DefaultValue("-1") @QueryParam("resultIndex") String resultIndex,
+            @DefaultValue("-1") @QueryParam("resultSize") String resultSize,
+            @Context HttpHeaders headers,
+            @Context HttpServletRequest req,
+            @Context UriInfo info) throws FileNotFoundException, AAIException {
         Set<String> roles = this.getRoles(req.getUserPrincipal());
 
-        return runner(TraversalConstants.AAI_TRAVERSAL_DSL_TIMEOUT_ENABLED,
-            TraversalConstants.AAI_TRAVERSAL_DSL_TIMEOUT_APP,
-            TraversalConstants.AAI_TRAVERSAL_DSL_TIMEOUT_LIMIT, headers, info, HttpMethod.PUT,
-            new AaiCallable() {
-                @Override
-                public Response process() throws Exception {
-                    return (processExecuteQuery(content, req, versionParam, queryFormat, subgraph,
-                        validate, headers, info, resultIndex, resultSize, roles));
-                }
-            });
+        return processExecuteQuery(dslQuery, req, versionParam, queryFormat, subgraph,
+                validate, headers, info, resultIndex, resultSize, roles);
     }
 
-    public Response processExecuteQuery(String content, HttpServletRequest req, String versionParam,
-        String queryFormat, String subgraph, String validate, HttpHeaders headers, UriInfo info,
-        String resultIndex, String resultSize, Set<String> roles) {
+    public Response processExecuteQuery(String dslQuery, HttpServletRequest request, String versionParam,
+            String queryFormat, String subgraph, String validate, HttpHeaders headers, UriInfo info,
+            String resultIndex, String resultSize, Set<String> roles) throws FileNotFoundException, AAIException {
 
-        String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
-        String dslOverride = headers.getRequestHeaders().getFirst("X-DslOverride");
+        final SchemaVersion version = new SchemaVersion(versionParam);
+        final String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+        final String dslOverride = headers.getRequestHeaders().getFirst("X-DslOverride");
 
         Optional<String> dslApiVersionHeader =
             Optional.ofNullable(headers.getRequestHeaders().getFirst("X-DslApiVersion"));
@@ -154,123 +146,110 @@ public class DslConsumer extends TraversalConsumer {
             }
         }
 
-        Response response;
-        SchemaVersion version = new SchemaVersion(versionParam);
-
-        TransactionalGraphEngine dbEngine = null;
-        try {
-            String serverBase =
-                req.getRequestURL().toString().replaceAll("/(v[0-9]+|latest)/.*", "/");
-            traversalUriHttpEntry.setHttpEntryProperties(version, serverBase);
-            traversalUriHttpEntry.setPaginationParameters(resultIndex, resultSize);
-            dbEngine = traversalUriHttpEntry.getDbEngine();
-            JsonObject input = JsonParser.parseString(content).getAsJsonObject();
-            JsonElement dslElement = input.get("dsl");
-            String dsl = "";
-            if (dslElement != null) {
-                dsl = dslElement.getAsString();
-            }
-
-            boolean isDslOverride = dslOverride != null
-                && !AAIConfig.get(TraversalConstants.DSL_OVERRIDE).equals("false")
-                && dslOverride.equals(AAIConfig.get(TraversalConstants.DSL_OVERRIDE));
+        String result = executeQuery(dslQuery, request, queryFormat, subgraph, validate, info.getQueryParameters(), resultIndex, resultSize,
+                roles, version, sourceOfTruth, dslOverride);
 
-            if (isDslOverride) {
-                dslQueryProcessor.setStartNodeValidationFlag(false);
-            }
-
-            dslQueryProcessor.setValidationRules(validate);
+        String acceptType = headers.getHeaderString("Accept");
+        if (acceptType == null) {
+            acceptType = MediaType.APPLICATION_JSON;
+        }
 
-            Format format = Format.getFormat(queryFormat);
+        if (MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(acceptType))) {
+            result = xmlFormatTransformer.transform(result);
+        }
 
-            if (isAggregate(format)) {
-                dslQueryProcessor.setAggregate(true);
-            }
+        if (traversalUriHttpEntry.isPaginated()) {
+            return Response.status(Status.OK).type(acceptType)
+                    .header("total-results", traversalUriHttpEntry.getTotalVertices())
+                    .header("total-pages", traversalUriHttpEntry.getTotalPaginationBuckets())
+                    .entity(result).build();
+        } else {
+            return Response.status(Status.OK).type(acceptType).entity(result).build();
+        }
+    }
 
-            if (isHistory(format)) {
-                validateHistoryParams(format, info.getQueryParameters());
-            }
+    private String executeQuery(String content, HttpServletRequest req, String queryFormat, String subgraph,
+            String validate, MultivaluedMap<String, String> queryParameters, String resultIndex, String resultSize, 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)/.*", "/");
+        traversalUriHttpEntry.setHttpEntryProperties(version, serverBase);
+        traversalUriHttpEntry.setPaginationParameters(resultIndex, resultSize);
+        final TransactionalGraphEngine dbEngine = traversalUriHttpEntry.getDbEngine();
+
+        JsonObject input = JsonParser.parseString(content).getAsJsonObject();
+        JsonElement dslElement = input.get("dsl");
+        String dsl = "";
+        if (dslElement != null) {
+            dsl = dslElement.getAsString();
+        }
 
-            GraphTraversalSource traversalSource =
-                getTraversalSource(dbEngine, format, info, roles);
+        boolean isDslOverride = dslOverride != null
+                && !AAIConfig.get(TraversalConstants.DSL_OVERRIDE).equals("false")
+                && dslOverride.equals(AAIConfig.get(TraversalConstants.DSL_OVERRIDE));
 
-            GenericQueryProcessor processor =
-                new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton)
-                    .queryFrom(dsl, "dsl").queryProcessor(dslQueryProcessor).version(dslApiVersion)
-                    .processWith(processorType).format(format).uriParams(info.getQueryParameters())
-                    .traversalSource(isHistory(format), traversalSource).create();
+        if (isDslOverride) {
+            dslQueryProcessor.setStartNodeValidationFlag(false);
+        }
 
-            SubGraphStyle subGraphStyle = SubGraphStyle.valueOf(subgraph);
-            List<Object> vertTemp = processor.execute(subGraphStyle);
+        dslQueryProcessor.setValidationRules(validate);
 
-            // Dedup if duplicate objects are returned in each array in the aggregate format
-            // scenario.
-            List<Object> vertTempDedupedObjectList = dedupObjectInAggregateFormatResult(vertTemp);
+        Format format = Format.getFormat(queryFormat);
 
-            List<Object> vertices;
-            if (isAggregate(format)) {
-                vertices = traversalUriHttpEntry
-                    .getPaginatedVertexListForAggregateFormat(vertTempDedupedObjectList);
-            } else {
-                vertices = traversalUriHttpEntry.getPaginatedVertexList(vertTemp);
-            }
+        if (isAggregate(format)) {
+            dslQueryProcessor.setAggregate(true);
+        }
 
-            DBSerializer serializer =
-                new DBSerializer(version, dbEngine, ModelType.MOXY, sourceOfTruth);
-            FormatFactory ff = new FormatFactory(traversalUriHttpEntry.getLoader(), serializer,
-                schemaVersions, this.basePath, serverBase);
+        if (isHistory(format)) {
+            validateHistoryParams(format, queryParameters);
+        }
 
-            MultivaluedMap<String, String> mvm = new MultivaluedHashMap<>();
-            mvm.putAll(info.getQueryParameters());
-            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();
-            }
+        GraphTraversalSource traversalSource =
+            getTraversalSource(dbEngine, format, queryParameters, roles);
 
-            String acceptType = headers.getHeaderString("Accept");
+        GenericQueryProcessor processor =
+            new GenericQueryProcessor.Builder(dbEngine, gremlinServerSingleton)
+                .queryFrom(dsl, "dsl").queryProcessor(dslQueryProcessor).version(dslApiVersion)
+                .processWith(processorType).format(format).uriParams(queryParameters)
+                .traversalSource(isHistory(format), traversalSource).create();
 
-            if (acceptType == null) {
-                acceptType = MediaType.APPLICATION_JSON;
-            }
+        SubGraphStyle subGraphStyle = SubGraphStyle.valueOf(subgraph);
+        List<Object> vertTemp = processor.execute(subGraphStyle);
 
-            if (MediaType.APPLICATION_XML_TYPE.isCompatible(MediaType.valueOf(acceptType))) {
-                result = xmlFormatTransformer.transform(result);
-            }
+        // Dedup if duplicate objects are returned in each array in the aggregate format
+        // scenario.
+        List<Object> vertTempDedupedObjectList = dedupObjectInAggregateFormatResult(vertTemp);
 
-            if (traversalUriHttpEntry.isPaginated()) {
-                response = Response.status(Status.OK).type(acceptType)
-                    .header("total-results", traversalUriHttpEntry.getTotalVertices())
-                    .header("total-pages", traversalUriHttpEntry.getTotalPaginationBuckets())
-                    .entity(result).build();
-            } else {
-                response = Response.status(Status.OK).type(acceptType).entity(result).build();
-            }
+        List<Object> vertices;
+        if (isAggregate(format)) {
+            vertices = traversalUriHttpEntry
+                    .getPaginatedVertexListForAggregateFormat(vertTempDedupedObjectList);
+        } else {
+            vertices = traversalUriHttpEntry.getPaginatedVertexList(vertTemp);
+        }
 
-        } catch (AAIException e) {
-            response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e);
-        } catch (SchemaViolationException sve) {
-            AAIException ex = new AAIException("AAI_4020", sve);
-            response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex);
-        } catch (Exception e) {
-            AAIException ex = new AAIException("AAI_4000", e);
-            response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex);
-        } finally {
-            if (dbEngine != null) {
-                dbEngine.rollback();
-            }
+        DBSerializer serializer =
+            new DBSerializer(version, dbEngine, ModelType.MOXY, sourceOfTruth);
+        FormatFactory ff = new FormatFactory(traversalUriHttpEntry.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)));
         }
-
-        return response;
+        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;
     }
 
     private List<Object> dedupObjectInAggregateFormatResult(List<Object> vertTemp) {
@@ -280,7 +259,7 @@ public class DslConsumer extends TraversalConsumer {
             Object o = itr.next();
             if (o instanceof ArrayList) {
                 vertTempDedupedObjectList
-                    .add(((ArrayList) o).stream().distinct().collect(Collectors.toList()));
+                        .add(((ArrayList) o).stream().distinct().collect(Collectors.toList()));
             }
         }
         return vertTempDedupedObjectList;
index f15e375..447ecdd 100644 (file)
@@ -26,6 +26,7 @@ import com.sun.istack.SAXParseException2;
 
 import java.util.ArrayList;
 
+import javax.annotation.Priority;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
@@ -35,6 +36,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.Provider;
 
+import org.janusgraph.core.SchemaViolationException;
 import org.onap.aai.exceptions.AAIException;
 import org.onap.aai.logging.ErrorLogHelper;
 
@@ -42,6 +44,7 @@ import org.onap.aai.logging.ErrorLogHelper;
  * The Class ExceptionHandler.
  */
 @Provider
+@Priority(10000)
 public class ExceptionHandler implements ExceptionMapper<Exception> {
 
     private static final String AAI_4007 = "AAI_4007";
@@ -58,47 +61,30 @@ public class ExceptionHandler implements ExceptionMapper<Exception> {
         // with a linked exception
         if (exception instanceof WebApplicationException) {
             if (exception.getCause() instanceof SAXParseException2) {
-                return buildInputParsingErrorResponse(exception, "UnmarshalException");
+                return buildAAIExceptionResponse(new AAIException(AAI_4007, exception));
             } else {
-                return ((WebApplicationException)exception).getResponse();
+                return ((WebApplicationException) exception).getResponse();
             }
         } else if (exception instanceof JsonParseException) {
             // jackson does it differently so we get the direct JsonParseException
-            return buildInputParsingErrorResponse(exception);
+            return buildAAIExceptionResponse(new AAIException(AAI_4007, exception));
         } else if (exception instanceof JsonMappingException) {
             // jackson does it differently so we get the direct JsonParseException
-            return buildInputParsingErrorResponse(exception);
+            return buildAAIExceptionResponse(new AAIException(AAI_4007, exception));
+        } else if (exception instanceof SchemaViolationException) {
+            return buildAAIExceptionResponse(new AAIException("AAI_4020", exception));
         // it didn't get set above, we wrap a general fault here
+        } else if (exception instanceof AAIException) {
+            return buildAAIExceptionResponse((AAIException) exception);
         } else {
             return defaultException(exception);
         }
     }
 
-    private Response buildInputParsingErrorResponse(Exception exception) {
-        ArrayList<String> templateVars = new ArrayList<>();
-        templateVars.add(exception.getClass().getSimpleName());
-        return buildInputParsingErrorResponse(exception, templateVars);
-    }
-
-    private Response buildInputParsingErrorResponse(Exception exception, String customExceptionName) {
-        ArrayList<String> templateVars = new ArrayList<>();
-        templateVars.add(customExceptionName);
-        return buildInputParsingErrorResponse(exception, templateVars);
-    }
-
-    private Response buildInputParsingErrorResponse(Exception exception, ArrayList<String> templateVars) {
-        AAIException ex = new AAIException(AAI_4007, exception);
-        return Response
-            .status(400).entity(ErrorLogHelper
-                .getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars))
-            .build();
-    }
-
-    private Response defaultException(Exception exception) {
+    private Response buildAAIExceptionResponse(AAIException exception) {
         ArrayList<String> templateVars = new ArrayList<>();
         templateVars.add(request.getMethod());
-        templateVars.add("unknown");
-        AAIException ex = new AAIException("AAI_4000", exception);
+        templateVars.add(request.getRequestURI());
 
         // prefer xml, use json otherwise
         return headers.getAcceptableMediaTypes().stream()
@@ -107,12 +93,16 @@ public class ExceptionHandler implements ExceptionMapper<Exception> {
             .map(xmlType -> 
                 Response.status(400).type(MediaType.APPLICATION_XML_TYPE)
                     .entity(ErrorLogHelper.getRESTAPIErrorResponse(
-                        headers.getAcceptableMediaTypes(), ex, templateVars))
+                        headers.getAcceptableMediaTypes(), exception, templateVars))
                     .build())
             .orElseGet(() -> 
                 Response.status(400).type(MediaType.APPLICATION_JSON_TYPE)
                 .entity(ErrorLogHelper.getRESTAPIErrorResponse(
-                    headers.getAcceptableMediaTypes(), ex, templateVars))
+                    headers.getAcceptableMediaTypes(), exception, templateVars))
                 .build());
     }
-}
+
+    private Response defaultException(Exception exception) {
+        return buildAAIExceptionResponse(new AAIException("AAI_4000", exception));
+    }
+}
\ No newline at end of file
index cade20c..5a2e19f 100644 (file)
@@ -215,7 +215,7 @@ public class QueryConsumer extends TraversalConsumer {
                 validateHistoryParams(format, info.getQueryParameters());
             }
             GraphTraversalSource traversalSource =
-                getTraversalSource(dbEngine, format, info, roles);
+                getTraversalSource(dbEngine, format, info.getQueryParameters(), roles);
             QueryStyle queryStyle = getQueryStyle(format, traversalUriHttpEntry);
 
             if (!startURIs.isEmpty()) {
index 2980f28..bc74308 100644 (file)
@@ -131,12 +131,12 @@ public abstract class TraversalConsumer extends RESTAPI {
     }
 
     protected GraphTraversalSource getTraversalSource(TransactionalGraphEngine dbEngine,
-        Format format, UriInfo info, Set<String> roles) throws AAIException {
+        Format format, MultivaluedMap<String, String> queryParameters, Set<String> roles) throws AAIException {
         GraphTraversalSource traversalSource;
 
         if (isHistory(format)) {
-            long localStartTime = this.getStartTime(format, info.getQueryParameters());
-            long localEndTime = this.getEndTime(info.getQueryParameters());
+            long localStartTime = this.getStartTime(format, queryParameters);
+            long localEndTime = this.getEndTime(queryParameters);
             traversalSource = dbEngine.asAdmin().getTraversalSource()
                 .withStrategies(getSubgraphStrategy(localStartTime, localEndTime, format));
         } else {
index feb8d1d..f4f3949 100644 (file)
@@ -78,6 +78,7 @@ public class JerseyConfiguration {
                 org.onap.aai.interceptors.pre.RequestModification.class,
                 org.onap.aai.interceptors.post.InvalidResponseStatus.class,
                 org.onap.aai.interceptors.post.ResponseTransactionLogging.class,
+                org.onap.aai.rest.ExceptionHandler.class,
                 org.onap.aai.interceptors.post.ResponseHeaderManipulation.class);
         resourceConfig.registerClasses(classes);
         logger.debug("REGISTERED CLASSES " + classes.toString());
index 81f47b1..ac6b749 100644 (file)
@@ -267,6 +267,7 @@ public class DslConsumerTest extends AbstractSpringRestTest {
         assertEquals("SVC6152", response.getBody().getRequestError().getServiceException().getMessageId());
         assertEquals("DSL Generic Error (msg=%1) (ec=%2)", response.getBody().getRequestError().getServiceException().getText());
         assertEquals("DSL Generic Error:Error while processing the query: org.onap.aai.exceptions.AAIException: No nodes marked for output", response.getBody().getRequestError().getServiceException().getVariables().get(0));
+        assertEquals("/aai/v11/dsl", response.getBody().getRequestError().getServiceException().getVariables().get(3));
     }
 
     @Test
index c7314bc..bed964e 100644 (file)
@@ -81,6 +81,7 @@ public class ExceptionHandlerTest {
         when(httpHeaders.getAcceptableMediaTypes()).thenReturn(outputMediaTypes);
         when(httpHeaders.getRequestHeaders()).thenReturn(headersMultiMap);
         when(request.getMethod()).thenReturn("PUT");
+        when(request.getRequestURI()).thenReturn("/aai/v14/dsl");
     }
 
     @Test
@@ -108,8 +109,8 @@ public class ExceptionHandlerTest {
         assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         assertEquals("SVC3102",responseEntity.getRequestError().getServiceException().getMessageId());
         assertEquals("Error parsing input performing %1 on %2 (msg=%3) (ec=%4)",responseEntity.getRequestError().getServiceException().getText());
-        assertEquals("UnmarshalException",responseEntity.getRequestError().getServiceException().getVariables().get(0));
-        assertEquals("null",responseEntity.getRequestError().getServiceException().getVariables().get(1));
+        assertEquals("PUT",responseEntity.getRequestError().getServiceException().getVariables().get(0));
+        assertEquals("/aai/v14/dsl",responseEntity.getRequestError().getServiceException().getVariables().get(1));
         assertEquals("Input parsing error:javax.ws.rs.WebApplicationException: HTTP 500 Internal Server Error",responseEntity.getRequestError().getServiceException().getVariables().get(2));
         assertEquals("ERR.5.4.4007",responseEntity.getRequestError().getServiceException().getVariables().get(3));
     }
@@ -127,8 +128,8 @@ public class ExceptionHandlerTest {
         assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         assertEquals("SVC3102",responseEntity.getRequestError().getServiceException().getMessageId());
         assertEquals("Error parsing input performing %1 on %2 (msg=%3) (ec=%4)",responseEntity.getRequestError().getServiceException().getText());
-        assertEquals("JsonParseException",responseEntity.getRequestError().getServiceException().getVariables().get(0));
-        assertEquals("null",responseEntity.getRequestError().getServiceException().getVariables().get(1));
+        assertEquals("PUT",responseEntity.getRequestError().getServiceException().getVariables().get(0));
+        assertEquals("/aai/v14/dsl",responseEntity.getRequestError().getServiceException().getVariables().get(1));
         assertEquals("Input parsing error:com.fasterxml.jackson.core.JsonParseException: ",responseEntity.getRequestError().getServiceException().getVariables().get(2));
         assertEquals("ERR.5.4.4007",responseEntity.getRequestError().getServiceException().getVariables().get(3));
     }
@@ -145,8 +146,8 @@ public class ExceptionHandlerTest {
         assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         assertEquals("SVC3102",responseEntity.getRequestError().getServiceException().getMessageId());
         assertEquals("Error parsing input performing %1 on %2 (msg=%3) (ec=%4)",responseEntity.getRequestError().getServiceException().getText());
-        assertEquals("JsonMappingException",responseEntity.getRequestError().getServiceException().getVariables().get(0));
-        assertEquals("null",responseEntity.getRequestError().getServiceException().getVariables().get(1));
+        assertEquals("PUT",responseEntity.getRequestError().getServiceException().getVariables().get(0));
+        assertEquals("/aai/v14/dsl",responseEntity.getRequestError().getServiceException().getVariables().get(1));
         assertEquals("Input parsing error:com.fasterxml.jackson.databind.JsonMappingException: ",responseEntity.getRequestError().getServiceException().getVariables().get(2));
         assertEquals("ERR.5.4.4007",responseEntity.getRequestError().getServiceException().getVariables().get(3));
     }
@@ -164,7 +165,7 @@ public class ExceptionHandlerTest {
         assertEquals("SVC3002",responseEntity.getRequestError().getServiceException().getMessageId());
         assertEquals("Error writing output performing %1 on %2 (msg=%3) (ec=%4)",responseEntity.getRequestError().getServiceException().getText());
         assertEquals("PUT",responseEntity.getRequestError().getServiceException().getVariables().get(0));
-        assertEquals("unknown",responseEntity.getRequestError().getServiceException().getVariables().get(1));
+        assertEquals("/aai/v14/dsl",responseEntity.getRequestError().getServiceException().getVariables().get(1));
         assertEquals("Internal Error:java.lang.Exception",responseEntity.getRequestError().getServiceException().getVariables().get(2));
         assertEquals("ERR.5.4.4000",responseEntity.getRequestError().getServiceException().getVariables().get(3));
     }
@@ -186,7 +187,7 @@ public class ExceptionHandlerTest {
         assertEquals("SVC3002",responseEntity.getRequestError().getServiceException().getMessageId());
         assertEquals("Error writing output performing %1 on %2 (msg=%3) (ec=%4)",responseEntity.getRequestError().getServiceException().getText());
         assertEquals("PUT",responseEntity.getRequestError().getServiceException().getVariables().get(0));
-        assertEquals("unknown",responseEntity.getRequestError().getServiceException().getVariables().get(1));
+        assertEquals("/aai/v14/dsl",responseEntity.getRequestError().getServiceException().getVariables().get(1));
         assertEquals("Internal Error:java.lang.Exception",responseEntity.getRequestError().getServiceException().getVariables().get(2));
         assertEquals("ERR.5.4.4000",responseEntity.getRequestError().getServiceException().getVariables().get(3));
     }