Repository: incubator-atlas Updated Branches: refs/heads/master 7c73f0c4a -> 19751c60b
ATLAS-805 Quickstart is failing if run after queries to the business taxonomy API (jspeidel via shwethags) Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/19751c60 Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/19751c60 Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/19751c60 Branch: refs/heads/master Commit: 19751c60b284346884e84ce8a38d7712750435a5 Parents: 7c73f0c Author: Shwetha GS <[email protected]> Authored: Fri May 20 20:39:58 2016 +0530 Committer: Shwetha GS <[email protected]> Committed: Fri May 20 20:39:58 2016 +0530 ---------------------------------------------------------------------- .../apache/atlas/catalog/query/BaseQuery.java | 35 +++- .../catalog/query/AtlasEntityQueryTest.java | 170 +++++++++++++++++++ release-log.txt | 1 + 3 files changed, 197 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/19751c60/catalog/src/main/java/org/apache/atlas/catalog/query/BaseQuery.java ---------------------------------------------------------------------- diff --git a/catalog/src/main/java/org/apache/atlas/catalog/query/BaseQuery.java b/catalog/src/main/java/org/apache/atlas/catalog/query/BaseQuery.java index ac8ca6b..c2eabf7 100644 --- a/catalog/src/main/java/org/apache/atlas/catalog/query/BaseQuery.java +++ b/catalog/src/main/java/org/apache/atlas/catalog/query/BaseQuery.java @@ -30,7 +30,10 @@ import org.apache.atlas.catalog.projection.Projection; import org.apache.atlas.catalog.projection.ProjectionResult; import org.apache.atlas.repository.graph.TitanGraphProvider; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; /** * Base Query implementation. @@ -50,7 +53,7 @@ public abstract class BaseQuery implements AtlasQuery { Collection<Map<String, Object>> resultMaps = new ArrayList<>(); for (Vertex vertex : executeQuery()) { - resultMaps.add(processPropertyMap(new VertexWrapper(vertex, resourceDefinition))); + resultMaps.add(processPropertyMap(wrapVertex(vertex))); } return resultMaps; } @@ -59,19 +62,29 @@ public abstract class BaseQuery implements AtlasQuery { GremlinPipeline pipeline = getInitialPipeline().as("root"); Pipe adapterPipe = queryExpression.asPipe(); - //todo: AlwaysQueryAdapter returns null for pipe - //todo: Is there a no-op pipe that I could add that wouldn't negatively affect performance - return adapterPipe == null ? - pipeline.toList() : - pipeline.add(adapterPipe).back("root").toList(); + try { + // AlwaysQuery returns null for pipe + List<Vertex> vertices = adapterPipe == null ? pipeline.toList() : + pipeline.add(adapterPipe).back("root").toList(); + + // Even non-mutating queries can result in objects being created in + // the graph such as new fields or property keys. So, it is important + // to commit the implicit query after execution, otherwise the uncommitted + // transaction will still be associated with the thread when it is re-pooled. + getGraph().commit(); + return vertices; + } catch (Throwable e) { + getGraph().rollback(); + throw e; + } } protected abstract GremlinPipeline getInitialPipeline(); // todo: consider getting protected Map<String, Object> processPropertyMap(VertexWrapper vertex) { - Map<String, Object> propertyMap = vertex.getPropertyMap(); - resourceDefinition.filterProperties(request, propertyMap); + Map<String, Object> propertyMap = resourceDefinition.filterProperties( + request, vertex.getPropertyMap()); addHref(propertyMap); return request.getCardinality() == Request.Cardinality.INSTANCE ? @@ -118,4 +131,8 @@ public abstract class BaseQuery implements AtlasQuery { protected TitanGraph getGraph() { return TitanGraphProvider.getGraphInstance(); } + + protected VertexWrapper wrapVertex(Vertex v) { + return new VertexWrapper(v, resourceDefinition); + } } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/19751c60/catalog/src/test/java/org/apache/atlas/catalog/query/AtlasEntityQueryTest.java ---------------------------------------------------------------------- diff --git a/catalog/src/test/java/org/apache/atlas/catalog/query/AtlasEntityQueryTest.java b/catalog/src/test/java/org/apache/atlas/catalog/query/AtlasEntityQueryTest.java new file mode 100644 index 0000000..838d4c1 --- /dev/null +++ b/catalog/src/test/java/org/apache/atlas/catalog/query/AtlasEntityQueryTest.java @@ -0,0 +1,170 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.atlas.catalog.query; + +import com.thinkaurelius.titan.core.TitanGraph; +import com.tinkerpop.blueprints.Vertex; +import com.tinkerpop.gremlin.java.GremlinPipeline; +import com.tinkerpop.pipes.Pipe; +import org.apache.atlas.catalog.Request; +import org.apache.atlas.catalog.VertexWrapper; +import org.apache.atlas.catalog.definition.ResourceDefinition; +import org.testng.annotations.Test; + +import java.util.*; + +import static org.easymock.EasyMock.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + +/** + * Unit tests for AtlasEntityQuery. + */ +@SuppressWarnings("unchecked") +public class AtlasEntityQueryTest { + //todo: add tests for instance query and getInitialPipeline() + @Test + public void testExecute_Collection() throws Exception { + TitanGraph graph = createStrictMock(TitanGraph.class); + QueryExpression expression = createStrictMock(QueryExpression.class); + ResourceDefinition resourceDefinition = createNiceMock(ResourceDefinition.class); + Request request = createNiceMock(Request.class); + Pipe queryExpressionPipe = createStrictMock(Pipe.class); + GremlinPipeline initialPipeline = createStrictMock(GremlinPipeline.class); + GremlinPipeline rootPipeline = createStrictMock(GremlinPipeline.class); + GremlinPipeline expressionPipeline = createStrictMock(GremlinPipeline.class); + Vertex vertex1 = createStrictMock(Vertex.class); + VertexWrapper vertex1Wrapper = createStrictMock(VertexWrapper.class); + + List<Vertex> results = new ArrayList<>(); + results.add(vertex1); + + Map<String, Object> vertex1PropertyMap = new HashMap<>(); + vertex1PropertyMap.put("prop1", "prop1.value1"); + vertex1PropertyMap.put("prop2", "prop2.value1"); + + Map<String, Object> filteredVertex1PropertyMap = new HashMap<>(); + filteredVertex1PropertyMap.put("prop1", "prop1.value1"); + + // mock expectations + expect(initialPipeline.as("root")).andReturn(rootPipeline); + expect(expression.asPipe()).andReturn(queryExpressionPipe); + expect(rootPipeline.add(queryExpressionPipe)).andReturn(expressionPipeline); + expect(expressionPipeline.back("root")).andReturn(rootPipeline); + expect(rootPipeline.toList()).andReturn(results); + graph.commit(); + expect(vertex1Wrapper.getPropertyMap()).andReturn(vertex1PropertyMap); + expect(resourceDefinition.filterProperties(request, vertex1PropertyMap)).andReturn(filteredVertex1PropertyMap); + expect(resourceDefinition.resolveHref(filteredVertex1PropertyMap)).andReturn("/foo/bar"); + expect(request.getCardinality()).andReturn(Request.Cardinality.COLLECTION); + + replay(graph, expression, resourceDefinition, request, queryExpressionPipe, + initialPipeline, rootPipeline, expressionPipeline, vertex1, vertex1Wrapper); + // end mock expectations + + AtlasEntityQuery query = new TestAtlasEntityQuery( + expression, resourceDefinition, request, initialPipeline, graph, vertex1Wrapper); + + // invoke method being tested + Collection<Map<String, Object>> queryResults = query.execute(); + + assertEquals(queryResults.size(), 1); + Map<String, Object> queryResultMap = queryResults.iterator().next(); + assertEquals(queryResultMap.size(), 2); + assertEquals(queryResultMap.get("prop1"), "prop1.value1"); + assertEquals(queryResultMap.get("href"), "/foo/bar"); + + verify(graph, expression, resourceDefinition, request, queryExpressionPipe, + initialPipeline, rootPipeline, expressionPipeline, vertex1, vertex1Wrapper); + } + + @Test + public void testExecute_Collection_rollbackOnException() throws Exception { + TitanGraph graph = createStrictMock(TitanGraph.class); + QueryExpression expression = createStrictMock(QueryExpression.class); + ResourceDefinition resourceDefinition = createNiceMock(ResourceDefinition.class); + Request request = createNiceMock(Request.class); + Pipe queryExpressionPipe = createStrictMock(Pipe.class); + GremlinPipeline initialPipeline = createStrictMock(GremlinPipeline.class); + GremlinPipeline rootPipeline = createStrictMock(GremlinPipeline.class); + GremlinPipeline expressionPipeline = createStrictMock(GremlinPipeline.class); + + // mock expectations + expect(initialPipeline.as("root")).andReturn(rootPipeline); + expect(expression.asPipe()).andReturn(queryExpressionPipe); + expect(rootPipeline.add(queryExpressionPipe)).andReturn(expressionPipeline); + expect(expressionPipeline.back("root")).andReturn(rootPipeline); + expect(rootPipeline.toList()).andThrow(new RuntimeException("something bad happened")); + graph.rollback(); + + replay(graph, expression, resourceDefinition, request, queryExpressionPipe, + initialPipeline, rootPipeline, expressionPipeline); + + // end mock expectations + + AtlasEntityQuery query = new TestAtlasEntityQuery( + expression, resourceDefinition, request, initialPipeline, graph, null); + + try { + // invoke method being tested + query.execute(); + fail("expected exception"); + } catch (RuntimeException e) { + assertEquals(e.getMessage(), "something bad happened"); + } + + verify(graph, expression, resourceDefinition, request, queryExpressionPipe, + initialPipeline, rootPipeline, expressionPipeline); + + } + + private class TestAtlasEntityQuery extends AtlasEntityQuery { + private final GremlinPipeline initialPipeline; + private final TitanGraph graph; + private final VertexWrapper vWrapper; + + public TestAtlasEntityQuery(QueryExpression queryExpression, + ResourceDefinition resourceDefinition, + Request request, + GremlinPipeline initialPipeline, + TitanGraph graph, + VertexWrapper vWrapper) { + + super(queryExpression, resourceDefinition, request); + this.initialPipeline = initialPipeline; + this.graph = graph; + this.vWrapper = vWrapper; + } + + @Override + protected GremlinPipeline getInitialPipeline() { + return initialPipeline; + } + + @Override + protected TitanGraph getGraph() { + return graph; + } + + @Override + protected VertexWrapper wrapVertex(Vertex v) { + return vWrapper; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/19751c60/release-log.txt ---------------------------------------------------------------------- diff --git a/release-log.txt b/release-log.txt index 486b2c5..b28a8fa 100644 --- a/release-log.txt +++ b/release-log.txt @@ -21,6 +21,7 @@ ATLAS-409 Atlas will not import avro tables with schema read from a file (dosset ATLAS-379 Create sqoop and falcon metadata addons (venkatnrangan,bvellanki,sowmyaramesh via shwethags) ALL CHANGES: +ATLAS-805 Quickstart is failing if run after queries to the business taxonomy API (jspeidel via shwethags) ATLAS-774 Better error handling from login.jsp (nixonrodrigues via shwethags) ATLAS-683 Refactor local type-system cache with cache provider interface (vmadugun via shwethags) ATLAS-802 New look UI to show Business Catalog functionalities (kevalbhatt18 via yhemanth)
