You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by sh...@apache.org on 2016/07/20 13:03:06 UTC

[3/5] incubator-atlas git commit: ATLAS-347 Atlas search APIs should allow pagination of results (shwethags)

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/085d5c86/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryService.java
----------------------------------------------------------------------
diff --git a/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryService.java b/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryService.java
deleted file mode 100644
index e347c2c..0000000
--- a/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryService.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * 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
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.atlas.discovery;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Metadata discovery service.
- */
-public interface DiscoveryService {
-
-    /**
-     * Full text search
-     */
-    String searchByFullText(String query) throws DiscoveryException;
-
-    /**
-     * Search using query DSL.
-     *
-     * @param dslQuery query in DSL format.
-     * @return JSON representing the type and results.
-     */
-    String searchByDSL(String dslQuery) throws DiscoveryException;
-
-    /**
-     * Assumes the User is familiar with the persistence structure of the Repository.
-     * The given query is run uninterpreted against the underlying Graph Store.
-     * The results are returned as a List of Rows. each row is a Map of Key,Value pairs.
-     *
-     * @param gremlinQuery query in gremlin dsl format
-     * @return List of Maps
-     * @throws org.apache.atlas.discovery.DiscoveryException
-     */
-    List<Map<String, String>> searchByGremlin(String gremlinQuery) throws DiscoveryException;
-}

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/085d5c86/webapp/src/main/java/org/apache/atlas/LocalAtlasClient.java
----------------------------------------------------------------------
diff --git a/webapp/src/main/java/org/apache/atlas/LocalAtlasClient.java b/webapp/src/main/java/org/apache/atlas/LocalAtlasClient.java
index 7173d4d..2b71489 100644
--- a/webapp/src/main/java/org/apache/atlas/LocalAtlasClient.java
+++ b/webapp/src/main/java/org/apache/atlas/LocalAtlasClient.java
@@ -229,22 +229,17 @@ public class LocalAtlasClient extends AtlasClient {
     }
 
     @Override
-    public JSONArray search(final String searchQuery) throws AtlasServiceException {
+    public JSONArray search(final String searchQuery, final int limit, final int offset) throws AtlasServiceException {
         throw new IllegalStateException("Not supported in LocalAtlasClient");
     }
 
     @Override
-    public JSONArray searchByDSL(final String query) throws AtlasServiceException {
+    public JSONArray searchByDSL(final String query, final int limit, final int offset) throws AtlasServiceException {
         throw new IllegalStateException("Not supported in LocalAtlasClient");
     }
 
     @Override
-    public JSONArray searchByGremlin(final String gremlinQuery) throws AtlasServiceException {
-        throw new IllegalStateException("Not supported in LocalAtlasClient");
-    }
-
-    @Override
-    public JSONObject searchByFullText(final String query) throws AtlasServiceException {
+    public JSONObject searchByFullText(final String query, final int limit, final int offset) throws AtlasServiceException {
         throw new IllegalStateException("Not supported in LocalAtlasClient");
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/085d5c86/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java
----------------------------------------------------------------------
diff --git a/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java b/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java
index 42bccec..1cdc4c7 100755
--- a/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java
+++ b/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java
@@ -462,7 +462,7 @@ public class QuickStart {
 
     private void search() throws Exception {
         for (String dslQuery : getDSLQueries()) {
-            JSONArray results = metadataServiceClient.search(dslQuery);
+            JSONArray results = metadataServiceClient.search(dslQuery, 10, 0);
             if (results != null) {
                 System.out.println("query [" + dslQuery + "] returned [" + results.length() + "] rows");
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/085d5c86/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java
----------------------------------------------------------------------
diff --git a/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java b/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java
index 256f7d3..1cfdbe8 100755
--- a/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java
+++ b/webapp/src/main/java/org/apache/atlas/web/resources/MetadataDiscoveryResource.java
@@ -20,10 +20,13 @@ package org.apache.atlas.web.resources;
 
 import com.google.common.base.Preconditions;
 import org.apache.atlas.AtlasClient;
-import org.apache.atlas.utils.AtlasPerfTracer;
-import org.apache.atlas.utils.ParamChecker;
+import org.apache.atlas.AtlasProperties;
+import org.apache.atlas.classification.InterfaceAudience;
 import org.apache.atlas.discovery.DiscoveryException;
 import org.apache.atlas.discovery.DiscoveryService;
+import org.apache.atlas.query.QueryParams;
+import org.apache.atlas.utils.AtlasPerfTracer;
+import org.apache.atlas.utils.ParamChecker;
 import org.apache.atlas.web.util.Servlets;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONException;
@@ -34,6 +37,7 @@ import org.slf4j.LoggerFactory;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -42,7 +46,6 @@ import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response;
 import java.util.List;
 import java.util.Map;
-import org.apache.hadoop.classification.InterfaceAudience;
 
 /**
  * Jersey Resource for metadata operations.
@@ -56,6 +59,7 @@ public class MetadataDiscoveryResource {
     private static final String QUERY_TYPE_DSL = "dsl";
     private static final String QUERY_TYPE_GREMLIN = "gremlin";
     private static final String QUERY_TYPE_FULLTEXT = "full-text";
+    private static final String LIMIT_OFFSET_DEFAULT = "-1";
 
     private final DiscoveryService discoveryService;
 
@@ -73,50 +77,49 @@ public class MetadataDiscoveryResource {
     /**
      * Search using a given query.
      *
-     * @param query search query in raw gremlin or DSL format falling back to full text.
+     * @param query search query in DSL format falling back to full text.
+     * @param limit number of rows to be returned in the result, used for pagination. maxlimit > limit > 0. -1 maps to atlas.search.defaultlimit property value
+     * @param offset offset to the results returned, used for pagination. offset >= 0. -1 maps to offset 0
      * @return JSON representing the type and results.
      */
     @GET
     @Path("search")
     @Consumes(Servlets.JSON_MEDIA_TYPE)
     @Produces(Servlets.JSON_MEDIA_TYPE)
-    public Response search(@QueryParam("query") String query) {
-        JSONObject response;
+    public Response search(@QueryParam("query") String query,
+                           @DefaultValue(LIMIT_OFFSET_DEFAULT) @QueryParam("limit") int limit,
+                           @DefaultValue(LIMIT_OFFSET_DEFAULT) @QueryParam("offset") int offset) {
         AtlasPerfTracer perf = null;
-        try {   // fall back to dsl
-            if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
-                perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "MetadataDiscoveryResource.search(" + query + ")");
-            }
-
-            ParamChecker.notEmpty(query, "query cannot be null");
-
-            final String jsonResultStr = discoveryService.searchByDSL(query);
-            response = new DSLJSONResponseBuilder().results(jsonResultStr).query(query).build();
-            return Response.ok(response).build();
-
-        } catch (IllegalArgumentException e) {
-            LOG.error("Unable to get entity list for empty query", e);
-            throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
-
-        } catch (Throwable throwable) {
-            LOG.error("Unable to get entity list for query {} using dsl", query, throwable);
-            return searchUsingFullText(query);
-        } finally {
-            AtlasPerfTracer.log(perf);
+        if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
+            perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "MetadataDiscoveryResource.search(" + query + ")");
+        }
+        Response response = searchUsingQueryDSL(query, limit, offset);
+        if (response.getStatus() != Response.Status.OK.getStatusCode()) {
+            response = searchUsingFullText(query, limit, offset);
         }
+        AtlasPerfTracer.log(perf);
+        return response;
     }
 
     /**
      * Search using query DSL format.
      *
      * @param dslQuery search query in DSL format.
+     * @param limit number of rows to be returned in the result, used for pagination. maxlimit > limit > 0. -1 maps to atlas.search.defaultlimit property value
+     * @param offset offset to the results returned, used for pagination. offset >= 0. -1 maps to offset 0
+     * Limit and offset in API are used in conjunction with limit and offset in DSL query
+     * Final limit = min(API limit, max(query limit - API offset, 0))
+     * Final offset = API offset + query offset
+     *
      * @return JSON representing the type and results.
      */
     @GET
     @Path("search/dsl")
     @Consumes(Servlets.JSON_MEDIA_TYPE)
     @Produces(Servlets.JSON_MEDIA_TYPE)
-    public Response searchUsingQueryDSL(@QueryParam("query") String dslQuery) {
+    public Response searchUsingQueryDSL(@QueryParam("query") String dslQuery,
+                                        @DefaultValue(LIMIT_OFFSET_DEFAULT) @QueryParam("limit") int limit,
+                                        @DefaultValue(LIMIT_OFFSET_DEFAULT) @QueryParam("offset") int offset) {
         AtlasPerfTracer perf = null;
         try {
             if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
@@ -124,7 +127,8 @@ public class MetadataDiscoveryResource {
             }
 
             ParamChecker.notEmpty(dslQuery, "dslQuery cannot be null");
-            final String jsonResultStr = discoveryService.searchByDSL(dslQuery);
+            QueryParams queryParams = validateQueryParams(limit, offset);
+            final String jsonResultStr = discoveryService.searchByDSL(dslQuery, queryParams);
 
             JSONObject response = new DSLJSONResponseBuilder().results(jsonResultStr).query(dslQuery).build();
 
@@ -140,6 +144,28 @@ public class MetadataDiscoveryResource {
         }
     }
 
+    private QueryParams validateQueryParams(int limitParam, int offsetParam) {
+        int maxLimit = AtlasProperties.getProperty(AtlasProperties.AtlasProperty.SEARCH_MAX_LIMIT);
+        int defaultLimit = AtlasProperties.getProperty(AtlasProperties.AtlasProperty.SEARCH_DEFAULT_LIMIT);
+
+        int limit = defaultLimit;
+        boolean limitSet = (limitParam != Integer.valueOf(LIMIT_OFFSET_DEFAULT));
+        if (limitSet) {
+            ParamChecker.lessThan(limitParam, maxLimit, "limit");
+            ParamChecker.greaterThan(limitParam, 0, "limit");
+            limit = limitParam;
+        }
+
+        int offset = 0;
+        boolean offsetSet = (offsetParam != Integer.valueOf(LIMIT_OFFSET_DEFAULT));
+        if (offsetSet) {
+            ParamChecker.greaterThan(offsetParam, -1, "offset");
+            offset = offsetParam;
+        }
+
+        return new QueryParams(limit, offset);
+    }
+
     /**
      * Search using raw gremlin query format.
      *
@@ -189,13 +215,18 @@ public class MetadataDiscoveryResource {
      * Search using full text search.
      *
      * @param query search query.
+     * @param limit number of rows to be returned in the result, used for pagination. maxlimit > limit > 0. -1 maps to atlas.search.defaultlimit property value
+     * @param offset offset to the results returned, used for pagination. offset >= 0. -1 maps to offset 0
+     * NOTE: Pagination is not implemented currently for full text search, so limit and offset are not used
      * @return JSON representing the type and results.
      */
     @GET
     @Path("search/fulltext")
     @Consumes(Servlets.JSON_MEDIA_TYPE)
     @Produces(Servlets.JSON_MEDIA_TYPE)
-    public Response searchUsingFullText(@QueryParam("query") String query) {
+    public Response searchUsingFullText(@QueryParam("query") String query,
+                                        @DefaultValue(LIMIT_OFFSET_DEFAULT) @QueryParam("limit") int limit,
+                                        @DefaultValue(LIMIT_OFFSET_DEFAULT) @QueryParam("offset") int offset) {
         AtlasPerfTracer perf = null;
         try {
             if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
@@ -203,7 +234,8 @@ public class MetadataDiscoveryResource {
             }
 
             ParamChecker.notEmpty(query, "query cannot be null or empty");
-            final String jsonResultStr = discoveryService.searchByFullText(query);
+            QueryParams queryParams = validateQueryParams(limit, offset);
+            final String jsonResultStr = discoveryService.searchByFullText(query, queryParams);
             JSONArray rowsJsonArr = new JSONArray(jsonResultStr);
 
             JSONObject response = new FullTextJSonResponseBuilder().results(rowsJsonArr).query(query).build();

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/085d5c86/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerIT.java
----------------------------------------------------------------------
diff --git a/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerIT.java b/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerIT.java
index 72f403e..1b47e6e 100644
--- a/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerIT.java
+++ b/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerIT.java
@@ -72,8 +72,7 @@ public class NotificationHookConsumerIT extends BaseResourceIT {
         waitFor(MAX_WAIT_TIME, new Predicate() {
             @Override
             public boolean evaluate() throws Exception {
-                JSONArray results = serviceClient.searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE,
-                        entity.get("name")));
+                JSONArray results = searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, entity.get("name")));
                 return results.length() == 1;
             }
         });
@@ -90,8 +89,7 @@ public class NotificationHookConsumerIT extends BaseResourceIT {
         waitFor(MAX_WAIT_TIME, new Predicate() {
             @Override
             public boolean evaluate() throws Exception {
-                JSONArray results = serviceClient.searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE,
-                        entity.get("name")));
+                JSONArray results = searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, entity.get("name")));
                 return results.length() == 1;
             }
         });
@@ -146,14 +144,13 @@ public class NotificationHookConsumerIT extends BaseResourceIT {
         waitFor(MAX_WAIT_TIME, new Predicate() {
             @Override
             public boolean evaluate() throws Exception {
-                JSONArray results = serviceClient.searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE,
-                        newName));
+                JSONArray results = searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, newName));
                 return results.length() == 1;
             }
         });
 
         //no entity with the old qualified name
-        JSONArray results = serviceClient.searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, dbName));
+        JSONArray results = searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, dbName));
         assertEquals(results.length(), 0);
 
     }
@@ -195,8 +192,7 @@ public class NotificationHookConsumerIT extends BaseResourceIT {
         waitFor(MAX_WAIT_TIME, new Predicate() {
             @Override
             public boolean evaluate() throws Exception {
-                JSONArray results = serviceClient.searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE,
-                        dbName));
+                JSONArray results = searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, dbName));
                 return results.length() == 1;
             }
         });

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/085d5c86/webapp/src/test/java/org/apache/atlas/web/resources/BaseResourceIT.java
----------------------------------------------------------------------
diff --git a/webapp/src/test/java/org/apache/atlas/web/resources/BaseResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/resources/BaseResourceIT.java
index 498db92..ffc5249 100755
--- a/webapp/src/test/java/org/apache/atlas/web/resources/BaseResourceIT.java
+++ b/webapp/src/test/java/org/apache/atlas/web/resources/BaseResourceIT.java
@@ -54,6 +54,7 @@ import org.apache.atlas.utils.ParamChecker;
 import org.apache.atlas.web.util.Servlets;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.lang.RandomStringUtils;
+import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -342,4 +343,8 @@ public abstract class BaseResourceIT {
             }
         };
     }
+
+    protected JSONArray searchByDSL(String dslQuery) throws AtlasServiceException {
+        return serviceClient.searchByDSL(dslQuery, 10, 0);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/085d5c86/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java
----------------------------------------------------------------------
diff --git a/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java
index d41041c..9102c75 100755
--- a/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java
+++ b/webapp/src/test/java/org/apache/atlas/web/resources/EntityJerseyResourceIT.java
@@ -178,8 +178,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
             }
         });
 
-        JSONArray results =
-                serviceClient.searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, dbName));
+        JSONArray results = searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, dbName));
         assertEquals(results.length(), 1);
 
         //create entity again shouldn't create another instance with same unique attribute value
@@ -197,7 +196,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
             //expected timeout
         }
 
-        results = serviceClient.searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, dbName));
+        results = searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, dbName));
         assertEquals(results.length(), 1);
 
         //Test the same across references
@@ -208,7 +207,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
         table.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, tableName);
 
         serviceClient.createEntity(table);
-        results = serviceClient.searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, dbName));
+        results = searchByDSL(String.format("%s where name='%s'", DATABASE_TYPE, dbName));
         assertEquals(results.length(), 1);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/085d5c86/webapp/src/test/java/org/apache/atlas/web/resources/MetadataDiscoveryJerseyResourceIT.java
----------------------------------------------------------------------
diff --git a/webapp/src/test/java/org/apache/atlas/web/resources/MetadataDiscoveryJerseyResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/resources/MetadataDiscoveryJerseyResourceIT.java
index a8c1213..606af92 100755
--- a/webapp/src/test/java/org/apache/atlas/web/resources/MetadataDiscoveryJerseyResourceIT.java
+++ b/webapp/src/test/java/org/apache/atlas/web/resources/MetadataDiscoveryJerseyResourceIT.java
@@ -24,6 +24,7 @@ import com.sun.jersey.api.client.ClientResponse;
 import com.sun.jersey.api.client.WebResource;
 
 import org.apache.atlas.AtlasClient;
+import org.apache.atlas.AtlasServiceException;
 import org.apache.atlas.typesystem.Referenceable;
 import org.apache.atlas.typesystem.Struct;
 import org.apache.atlas.typesystem.TypesDef;
@@ -47,11 +48,16 @@ import javax.ws.rs.core.Response;
 
 import java.util.List;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
 /**
  * Search Integration Tests.
  */
 public class MetadataDiscoveryJerseyResourceIT extends BaseResourceIT {
 
+    private String tagName;
+
     @BeforeClass
     public void setUp() throws Exception {
         super.setUp();
@@ -67,7 +73,7 @@ public class MetadataDiscoveryJerseyResourceIT extends BaseResourceIT {
 
         ClientResponse clientResponse = resource.accept(Servlets.JSON_MEDIA_TYPE).type(Servlets.JSON_MEDIA_TYPE)
                 .method(HttpMethod.GET, ClientResponse.class);
-        Assert.assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
+        assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
 
         String responseAsString = clientResponse.getEntity(String.class);
         Assert.assertNotNull(responseAsString);
@@ -75,16 +81,71 @@ public class MetadataDiscoveryJerseyResourceIT extends BaseResourceIT {
         JSONObject response = new JSONObject(responseAsString);
         Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID));
 
-        Assert.assertEquals(response.getString("query"), dslQuery);
-        Assert.assertEquals(response.getString("queryType"), "dsl");
+        assertEquals(response.getString("query"), dslQuery);
+        assertEquals(response.getString("queryType"), "dsl");
 
         JSONArray results = response.getJSONArray(AtlasClient.RESULTS);
         Assert.assertNotNull(results);
-        Assert.assertEquals(results.length(), 1);
+        assertEquals(results.length(), 1);
 
         int numRows = response.getInt(AtlasClient.COUNT);
-        Assert.assertEquals(numRows, 1);
+        assertEquals(numRows, 1);
+    }
 
+    @Test
+    public void testSearchDSLLimits() throws Exception {
+        Referenceable entity = new Referenceable("dsl_test_type");
+        entity.set("name", randomString());
+        entity.set("description", randomString());
+        createInstance(entity);
+
+        //search without new parameters of limit and offset should work
+        String dslQuery = "from dsl_test_type";
+        WebResource resource = service.path("api/atlas/discovery/search/dsl").queryParam("query", dslQuery);
+
+        ClientResponse clientResponse = resource.accept(Servlets.JSON_MEDIA_TYPE).type(Servlets.JSON_MEDIA_TYPE)
+                                                .method(HttpMethod.GET, ClientResponse.class);
+        assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
+
+        //higher limit, all results returned
+        JSONArray results = serviceClient.searchByDSL(dslQuery, 10, 0);
+        assertEquals(results.length(), 2);
+
+        //default limit and offset -1, all results returned
+        results = serviceClient.searchByDSL(dslQuery, -1, -1);
+        assertEquals(results.length(), 2);
+
+        //uses the limit parameter passed
+        results = serviceClient.searchByDSL(dslQuery, 1, 0);
+        assertEquals(results.length(), 1);
+
+        //uses the offset parameter passed
+        results = serviceClient.searchByDSL(dslQuery, 10, 1);
+        assertEquals(results.length(), 1);
+
+        //limit > 0
+        try {
+            serviceClient.searchByDSL(dslQuery, 0, 10);
+            fail("Expected BAD_REQUEST");
+        } catch (AtlasServiceException e) {
+            assertEquals(e.getStatus(), ClientResponse.Status.BAD_REQUEST, "Got " + e.getStatus());
+        }
+
+        //limit > maxlimit
+        try {
+            serviceClient.searchByDSL(dslQuery, Integer.MAX_VALUE, 10);
+            fail("Expected BAD_REQUEST");
+        } catch (AtlasServiceException e) {
+            assertEquals(e.getStatus(), ClientResponse.Status.BAD_REQUEST, "Got " + e.getStatus());
+        }
+
+        //offset >= 0
+        try {
+            serviceClient.searchByDSL(dslQuery, 10, -2);
+            fail("Expected BAD_REQUEST");
+        } catch (AtlasServiceException e) {
+            assertEquals(e.getStatus(), ClientResponse.Status.BAD_REQUEST, "Got " + e.getStatus());
+        }
     }
 
     @Test
@@ -94,7 +155,7 @@ public class MetadataDiscoveryJerseyResourceIT extends BaseResourceIT {
 
         ClientResponse clientResponse = resource.accept(Servlets.JSON_MEDIA_TYPE).type(Servlets.JSON_MEDIA_TYPE)
                 .method(HttpMethod.GET, ClientResponse.class);
-        Assert.assertEquals(clientResponse.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
+        assertEquals(clientResponse.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
     }
 
     @Test
@@ -104,7 +165,7 @@ public class MetadataDiscoveryJerseyResourceIT extends BaseResourceIT {
 
         ClientResponse clientResponse = resource.accept(Servlets.JSON_MEDIA_TYPE).type(Servlets.JSON_MEDIA_TYPE)
                 .method(HttpMethod.GET, ClientResponse.class);
-        Assert.assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
+        assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
 
         String responseAsString = clientResponse.getEntity(String.class);
         Assert.assertNotNull(responseAsString);
@@ -112,8 +173,8 @@ public class MetadataDiscoveryJerseyResourceIT extends BaseResourceIT {
         JSONObject response = new JSONObject(responseAsString);
         Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID));
 
-        Assert.assertEquals(response.getString("query"), query);
-        Assert.assertEquals(response.getString("queryType"), "gremlin");
+        assertEquals(response.getString("query"), query);
+        assertEquals(response.getString("queryType"), "gremlin");
     }
 
     @Test
@@ -123,7 +184,7 @@ public class MetadataDiscoveryJerseyResourceIT extends BaseResourceIT {
 
         ClientResponse clientResponse = resource.accept(Servlets.JSON_MEDIA_TYPE).type(Servlets.JSON_MEDIA_TYPE)
                 .method(HttpMethod.GET, ClientResponse.class);
-        Assert.assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
+        assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
 
         String responseAsString = clientResponse.getEntity(String.class);
         Assert.assertNotNull(responseAsString);
@@ -131,29 +192,28 @@ public class MetadataDiscoveryJerseyResourceIT extends BaseResourceIT {
         JSONObject response = new JSONObject(responseAsString);
         Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID));
 
-        Assert.assertEquals(response.getString("query"), query);
-        Assert.assertEquals(response.getString("queryType"), "dsl");
+        assertEquals(response.getString("query"), query);
+        assertEquals(response.getString("queryType"), "dsl");
     }
 
-    @Test(enabled = false)
+    @Test
     public void testSearchUsingFullText() throws Exception {
-        String query = "foundation_etl";
-        JSONObject response = serviceClient.searchByFullText(query);
+        JSONObject response = serviceClient.searchByFullText(tagName, 10, 0);
         Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID));
 
-        Assert.assertEquals(response.getString("query"), query);
-        Assert.assertEquals(response.getString("queryType"), "full-text");
+        assertEquals(response.getString("query"), tagName);
+        assertEquals(response.getString("queryType"), "full-text");
 
         JSONArray results = response.getJSONArray(AtlasClient.RESULTS);
-        Assert.assertEquals(results.length(), 1);
+        assertEquals(results.length(), 1, "Results: " + results);
 
         JSONObject row = results.getJSONObject(0);
         Assert.assertNotNull(row.get("guid"));
-        Assert.assertEquals(row.getString("typeName"), "dsl_test_type");
+        assertEquals(row.getString("typeName"), "dsl_test_type");
         Assert.assertNotNull(row.get("score"));
 
         int numRows = response.getInt(AtlasClient.COUNT);
-        Assert.assertEquals(numRows, 1);
+        assertEquals(numRows, 1);
     }
 
     private void createTypes() throws Exception {
@@ -165,37 +225,22 @@ public class MetadataDiscoveryJerseyResourceIT extends BaseResourceIT {
         HierarchicalTypeDefinition<TraitType> classificationTraitDefinition = TypesUtil
                 .createTraitTypeDef("Classification", ImmutableSet.<String>of(),
                         TypesUtil.createRequiredAttrDef("tag", DataTypes.STRING_TYPE));
-        HierarchicalTypeDefinition<TraitType> piiTrait =
-                TypesUtil.createTraitTypeDef("PII_TYPE", ImmutableSet.<String>of());
-        HierarchicalTypeDefinition<TraitType> phiTrait =
-                TypesUtil.createTraitTypeDef("PHI", ImmutableSet.<String>of());
-        HierarchicalTypeDefinition<TraitType> pciTrait =
-                TypesUtil.createTraitTypeDef("PCI", ImmutableSet.<String>of());
-        HierarchicalTypeDefinition<TraitType> soxTrait =
-                TypesUtil.createTraitTypeDef("SOX", ImmutableSet.<String>of());
-        HierarchicalTypeDefinition<TraitType> secTrait =
-                TypesUtil.createTraitTypeDef("SEC", ImmutableSet.<String>of());
-        HierarchicalTypeDefinition<TraitType> financeTrait =
-                TypesUtil.createTraitTypeDef("Finance", ImmutableSet.<String>of());
-
         TypesDef typesDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), ImmutableList.<StructTypeDefinition>of(),
-                        ImmutableList
-                                .of(classificationTraitDefinition, piiTrait, phiTrait, pciTrait, soxTrait, secTrait,
-                                        financeTrait), ImmutableList.of(dslTestTypeDefinition));
+                        ImmutableList.of(classificationTraitDefinition), ImmutableList.of(dslTestTypeDefinition));
         createType(typesDef);
     }
 
     private Id createInstance() throws Exception {
-        Referenceable entityInstance =
-                new Referenceable("dsl_test_type", "Classification", "PII_TYPE", "PHI", "PCI", "SOX", "SEC", "Finance");
+        Referenceable entityInstance = new Referenceable("dsl_test_type", "Classification");
         entityInstance.set("name", "foo name");
         entityInstance.set("description", "bar description");
 
         Struct traitInstance = (Struct) entityInstance.getTrait("Classification");
-        traitInstance.set("tag", "foundation_etl");
+        tagName = randomString();
+        traitInstance.set("tag", tagName);
 
         List<String> traits = entityInstance.getTraits();
-        Assert.assertEquals(traits.size(), 7);
+        assertEquals(traits.size(), 1);
 
         return createInstance(entityInstance);
     }