Repository: incubator-atlas Updated Branches: refs/heads/master bbf48d90a -> 143f21039
ATLAS-232 Fix the API incompatibility introduced in ATLAS-58 (shwetags via sumasai) Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/143f2103 Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/143f2103 Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/143f2103 Branch: refs/heads/master Commit: 143f21039f264d523b9dc6bc88bca44e3ef6dc41 Parents: bbf48d9 Author: Suma Shivaprasad <[email protected]> Authored: Mon Oct 26 10:16:47 2015 +0530 Committer: Suma Shivaprasad <[email protected]> Committed: Mon Oct 26 10:16:47 2015 +0530 ---------------------------------------------------------------------- .../main/java/org/apache/atlas/AtlasClient.java | 5 +- release-log.txt | 3 +- .../atlas/web/resources/EntitiesResource.java | 133 ------------------- .../atlas/web/resources/EntityResource.java | 108 ++++++++++++++- .../web/resources/EntityJerseyResourceIT.java | 24 +++- 5 files changed, 128 insertions(+), 145 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/143f2103/client/src/main/java/org/apache/atlas/AtlasClient.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/atlas/AtlasClient.java b/client/src/main/java/org/apache/atlas/AtlasClient.java index 06d9206..8f04653 100755 --- a/client/src/main/java/org/apache/atlas/AtlasClient.java +++ b/client/src/main/java/org/apache/atlas/AtlasClient.java @@ -67,7 +67,6 @@ public class AtlasClient { public static final String BASE_URI = "api/atlas/"; public static final String TYPES = "types"; public static final String URI_ENTITY = "entity"; - public static final String URI_ENTITIES = "entities"; public static final String URI_SEARCH = "discovery/search"; public static final String URI_LINEAGE = "lineage/hive/table"; @@ -138,10 +137,10 @@ public class AtlasClient { LIST_TRAIT_TYPES(BASE_URI + TYPES + "?type=trait", HttpMethod.GET), //Entity operations - CREATE_ENTITY(BASE_URI + URI_ENTITIES, HttpMethod.POST), + CREATE_ENTITY(BASE_URI + URI_ENTITY, HttpMethod.POST), GET_ENTITY(BASE_URI + URI_ENTITY, HttpMethod.GET), UPDATE_ENTITY(BASE_URI + URI_ENTITY, HttpMethod.PUT), - LIST_ENTITIES(BASE_URI + URI_ENTITIES, HttpMethod.GET), + LIST_ENTITIES(BASE_URI + URI_ENTITY, HttpMethod.GET), //Trait operations ADD_TRAITS(BASE_URI + URI_ENTITY, HttpMethod.POST), http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/143f2103/release-log.txt ---------------------------------------------------------------------- diff --git a/release-log.txt b/release-log.txt index b50ee43..3daa7c4 100644 --- a/release-log.txt +++ b/release-log.txt @@ -9,7 +9,8 @@ ATLAS-54 Rename configs in hive hook (shwethags) ATLAS-3 Mixed Index creation fails with Date types (sumasai via shwethags) ALL CHANGES: -ATLAS1-98 Atlas UI Requires Internet Access(sanjayp via sumasai) +ATLAS-232 Fix the API incompatibility introduced in ATLAS-58(shwethags via sumasai) +ATLAS-198 Atlas UI Requires Internet Access(sanjayp via sumasai) ATLAS-201 Rename org.apache.atlas.Main to org.apache.atlas.Atlas (rishabhbhardwaj via shwethags) ATLAS-179 Atlas hook causes mem leak and hive server 2 crashes (shwethags) ATLAS-212 Remove test class usage of hive configuration property "atlas.rest.address" (jspeidel via shwethags) http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/143f2103/webapp/src/main/java/org/apache/atlas/web/resources/EntitiesResource.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/atlas/web/resources/EntitiesResource.java b/webapp/src/main/java/org/apache/atlas/web/resources/EntitiesResource.java deleted file mode 100644 index 8cff0c5..0000000 --- a/webapp/src/main/java/org/apache/atlas/web/resources/EntitiesResource.java +++ /dev/null @@ -1,133 +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 - * <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.web.resources; - -import com.google.common.base.Preconditions; -import com.google.inject.Inject; -import org.apache.atlas.AtlasClient; -import org.apache.atlas.AtlasException; -import org.apache.atlas.repository.EntityExistsException; -import org.apache.atlas.services.MetadataService; -import org.apache.atlas.typesystem.types.ValueConversionException; -import org.apache.atlas.web.util.Servlets; -import org.codehaus.jettison.json.JSONArray; -import org.codehaus.jettison.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.inject.Singleton; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; -import java.net.URI; -import java.util.List; - -@Path("entities") -@Singleton -public class EntitiesResource { - private static final Logger LOG = LoggerFactory.getLogger(EntitiesResource.class); - - @Inject - private MetadataService metadataService; - - @Context - UriInfo uriInfo; - - /** - * Submits the entity definitions (instances). - * The body contains the JSONArray of entity json. The service takes care of de-duping the entities based on any - * unique attribute for the give type. - */ - @POST - @Consumes(Servlets.JSON_MEDIA_TYPE) - @Produces(Servlets.JSON_MEDIA_TYPE) - public Response submit(@Context HttpServletRequest request) { - try { - final String entities = Servlets.getRequestPayload(request); - LOG.debug("submitting entities {} ", AtlasClient.toString(new JSONArray(entities))); - - final String guids = metadataService.createEntities(entities); - - UriBuilder ub = uriInfo.getAbsolutePathBuilder(); - URI locationURI = ub.path(guids).build(); - - JSONObject response = new JSONObject(); - response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId()); - response.put(AtlasClient.GUID, new JSONArray(guids)); - response.put(AtlasClient.DEFINITION, metadataService.getEntityDefinition(new JSONArray(guids).getString(0))); - - return Response.created(locationURI).entity(response).build(); - - } catch(EntityExistsException e) { - LOG.error("Unique constraint violation", e); - throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.CONFLICT)); - } catch (ValueConversionException ve) { - LOG.error("Unable to persist entity instance due to a desrialization error ", ve); - throw new WebApplicationException(Servlets.getErrorResponse(ve.getCause(), Response.Status.BAD_REQUEST)); - } catch (AtlasException | IllegalArgumentException e) { - LOG.error("Unable to persist entity instance", e); - throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST)); - } catch (Throwable e) { - LOG.error("Unable to persist entity instance", e); - throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR)); - } - } - - /** - * Gets the list of entities for a given entity type. - * - * @param entityType name of a type which is unique - */ - @GET - @Produces(Servlets.JSON_MEDIA_TYPE) - public Response getEntityListByType(@QueryParam("type") String entityType) { - try { - Preconditions.checkNotNull(entityType, "Entity type cannot be null"); - - LOG.debug("Fetching entity list for type={} ", entityType); - final List<String> entityList = metadataService.getEntityList(entityType); - - JSONObject response = new JSONObject(); - response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId()); - response.put(AtlasClient.TYPENAME, entityType); - response.put(AtlasClient.RESULTS, new JSONArray(entityList)); - response.put(AtlasClient.COUNT, entityList.size()); - - return Response.ok(response).build(); - } catch (NullPointerException e) { - LOG.error("Entity type cannot be null", e); - throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST)); - } catch (AtlasException | IllegalArgumentException e) { - LOG.error("Unable to get entity list for type {}", entityType, e); - throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST)); - } catch (Throwable e) { - LOG.error("Unable to get entity list for type {}", entityType, e); - throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR)); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/143f2103/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java b/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java index d8ffe9f..0820d9c 100755 --- a/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java +++ b/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java @@ -23,10 +23,14 @@ import org.apache.atlas.AtlasClient; import org.apache.atlas.AtlasException; import org.apache.atlas.ParamChecker; import org.apache.atlas.TypeNotFoundException; +import org.apache.atlas.repository.EntityExistsException; import org.apache.atlas.repository.EntityNotFoundException; import org.apache.atlas.services.MetadataService; +import org.apache.atlas.typesystem.types.ValueConversionException; import org.apache.atlas.web.util.Servlets; +import org.apache.commons.lang.StringUtils; import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,6 +87,57 @@ public class EntityResource { /** + * Submits the entity definitions (instances). + * The body contains the JSONArray of entity json. The service takes care of de-duping the entities based on any + * unique attribute for the give type. + */ + @POST + @Consumes(Servlets.JSON_MEDIA_TYPE) + @Produces(Servlets.JSON_MEDIA_TYPE) + public Response submit(@Context HttpServletRequest request) { + try { + String entities = Servlets.getRequestPayload(request); + + //Handle backward compatibility - if entities is not JSONArray, convert to JSONArray + try { + new JSONArray(entities); + } catch (JSONException e) { + final String finalEntities = entities; + entities = new JSONArray() {{ + put(finalEntities); + }}.toString(); + } + + LOG.debug("submitting entities {} ", AtlasClient.toString(new JSONArray(entities))); + + final String guids = metadataService.createEntities(entities); + + UriBuilder ub = uriInfo.getAbsolutePathBuilder(); + URI locationURI = ub.path(guids).build(); + + JSONObject response = new JSONObject(); + response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId()); + response.put(AtlasClient.GUID, new JSONArray(guids)); + response.put(AtlasClient.DEFINITION, metadataService.getEntityDefinition(new JSONArray(guids).getString(0))); + + return Response.created(locationURI).entity(response).build(); + + } catch(EntityExistsException e) { + LOG.error("Unique constraint violation", e); + throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.CONFLICT)); + } catch (ValueConversionException ve) { + LOG.error("Unable to persist entity instance due to a desrialization error ", ve); + throw new WebApplicationException(Servlets.getErrorResponse(ve.getCause(), Response.Status.BAD_REQUEST)); + } catch (AtlasException | IllegalArgumentException e) { + LOG.error("Unable to persist entity instance", e); + throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST)); + } catch (Throwable e) { + LOG.error("Unable to persist entity instance", e); + throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR)); + } + } + + /** * Fetch the complete definition of an entity given its GUID. * * @param guid GUID for the entity @@ -124,20 +179,61 @@ public class EntityResource { } /** + * Gets the list of entities for a given entity type. + * + * @param entityType name of a type which is unique + */ + public Response getEntityListByType(String entityType) { + try { + Preconditions.checkNotNull(entityType, "Entity type cannot be null"); + + LOG.debug("Fetching entity list for type={} ", entityType); + final List<String> entityList = metadataService.getEntityList(entityType); + + JSONObject response = new JSONObject(); + response.put(AtlasClient.REQUEST_ID, Servlets.getRequestId()); + response.put(AtlasClient.TYPENAME, entityType); + response.put(AtlasClient.RESULTS, new JSONArray(entityList)); + response.put(AtlasClient.COUNT, entityList.size()); + + return Response.ok(response).build(); + } catch (NullPointerException e) { + LOG.error("Entity type cannot be null", e); + throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST)); + } catch (AtlasException | IllegalArgumentException e) { + LOG.error("Unable to get entity list for type {}", entityType, e); + throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST)); + } catch (Throwable e) { + LOG.error("Unable to get entity list for type {}", entityType, e); + throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR)); + } + } + + @GET + @Produces(Servlets.JSON_MEDIA_TYPE) + public Response getEntity(@QueryParam("type") String entityType, + @QueryParam("property") String attribute, + @QueryParam("value") String value) { + if (StringUtils.isEmpty(attribute)) { + //List API + return getEntityListByType(entityType); + } else { + //Get entity by unique attribute + return getEntityDefinitionByAttribute(entityType, attribute, value); + } + } + + /** * Fetch the complete definition of an entity given its qualified name. * * @param entityType * @param attribute * @param value */ - @GET - @Produces(Servlets.JSON_MEDIA_TYPE) - public Response getEntityDefinitionByAttribute(@QueryParam("type") String entityType, - @QueryParam("property") String attribute, - @QueryParam("value") String value) { + public Response getEntityDefinitionByAttribute(String entityType, String attribute, String value) { try { LOG.debug("Fetching entity definition for type={}, qualified name={}", entityType, value); - ParamChecker.notEmpty(entityType, "type cannot be null"); + ParamChecker.notEmpty(entityType, "Entity type cannot be null"); ParamChecker.notEmpty(attribute, "attribute name cannot be null"); ParamChecker.notEmpty(value, "attribute value cannot be null"); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/143f2103/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 43ad941..e7fba6f 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 @@ -91,6 +91,26 @@ public class EntityJerseyResourceIT extends BaseResourceIT { } } + @Test + public void testSubmitSingleEntity() throws Exception { + Referenceable databaseInstance = new Referenceable(DATABASE_TYPE); + databaseInstance.set("name", randomString()); + databaseInstance.set("description", randomString()); + + ClientResponse clientResponse = + service.path("api/atlas/entity").accept(Servlets.JSON_MEDIA_TYPE).type(Servlets.JSON_MEDIA_TYPE) + .method(HttpMethod.POST, ClientResponse.class, + InstanceSerialization.toJson(databaseInstance, true)); + Assert.assertEquals(clientResponse.getStatus(), Response.Status.CREATED.getStatusCode()); + + String responseAsString = clientResponse.getEntity(String.class); + Assert.assertNotNull(responseAsString); + + JSONObject response = new JSONObject(responseAsString); + Assert.assertNotNull(response.get(AtlasClient.REQUEST_ID)); + Assert.assertNotNull(response.get(AtlasClient.GUID)); + } + @DataProvider public Object[][] invalidAttrValues() { return new Object[][]{{null}, {""}}; @@ -264,7 +284,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT { @Test public void testGetEntityListForBadEntityType() throws Exception { ClientResponse clientResponse = - service.path("api/atlas/entities").queryParam("type", "blah").accept(Servlets.JSON_MEDIA_TYPE) + service.path("api/atlas/entity").queryParam("type", "blah").accept(Servlets.JSON_MEDIA_TYPE) .type(Servlets.JSON_MEDIA_TYPE).method(HttpMethod.GET, ClientResponse.class); Assert.assertEquals(clientResponse.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); @@ -282,7 +302,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT { String typeName = addNewType(); ClientResponse clientResponse = - service.path("api/atlas/entities").queryParam("type", typeName).accept(Servlets.JSON_MEDIA_TYPE) + service.path("api/atlas/entity").queryParam("type", typeName).accept(Servlets.JSON_MEDIA_TYPE) .type(Servlets.JSON_MEDIA_TYPE).method(HttpMethod.GET, ClientResponse.class); Assert.assertEquals(clientResponse.getStatus(), Response.Status.OK.getStatusCode());
