FALCON-1438 Falcon RestAPI - In case of error falcon responds with FalconWebException::null. Contributed by Balu Vellanki.
Project: http://git-wip-us.apache.org/repos/asf/falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/falcon/commit/e5a1d597 Tree: http://git-wip-us.apache.org/repos/asf/falcon/tree/e5a1d597 Diff: http://git-wip-us.apache.org/repos/asf/falcon/diff/e5a1d597 Branch: refs/heads/master Commit: e5a1d597cd23e6bb044ec63df261d765419f20ac Parents: 1c97955 Author: Ajay Yadava <[email protected]> Authored: Thu Sep 10 14:24:04 2015 +0530 Committer: Ajay Yadava <[email protected]> Committed: Thu Sep 10 14:24:04 2015 +0530 ---------------------------------------------------------------------- CHANGES.txt | 2 + .../org/apache/falcon/FalconWebException.java | 50 ++++++++++---------- .../metadata/AbstractMetadataResource.java | 11 ++--- .../metadata/LineageMetadataResource.java | 25 +++++----- .../metadata/MetadataDiscoveryResource.java | 14 +++--- .../metadata/LineageMetadataResourceTest.java | 14 +++--- .../metadata/MetadataDiscoveryResourceTest.java | 16 +++---- .../resource/ProcessInstanceManagerIT.java | 7 +++ 8 files changed, 71 insertions(+), 68 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/falcon/blob/e5a1d597/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 613405b..2210d3b 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -20,6 +20,8 @@ Trunk (Unreleased) OPTIMIZATIONS BUG FIXES + FALCON-1438 Falcon RestAPI - In case of error falcon responds with FalconWebException::null(Balu Vellanki via Ajay Yadava). + FALCON-1415 Hive DR process fail if there are no events available from source table(Peeyush Bishnoi via Ajay Yadava) FALCON-1371 Status of scheduled Process entity is shown as submitted in corner case(Balu Vellanki via Sowmya Ramesh) http://git-wip-us.apache.org/repos/asf/falcon/blob/e5a1d597/prism/src/main/java/org/apache/falcon/FalconWebException.java ---------------------------------------------------------------------- diff --git a/prism/src/main/java/org/apache/falcon/FalconWebException.java b/prism/src/main/java/org/apache/falcon/FalconWebException.java index d9a3be7..7f8d0cd 100644 --- a/prism/src/main/java/org/apache/falcon/FalconWebException.java +++ b/prism/src/main/java/org/apache/falcon/FalconWebException.java @@ -49,55 +49,57 @@ public class FalconWebException extends WebApplicationException { return newException(e.getMessage(), status); } - public static FalconWebException newInstanceException(Throwable e, Response.Status status) { - return newInstanceException(getMessage(e), status); - } - - public static FalconWebException newTriageResultException(Throwable e, Response.Status status) { String message = getMessage(e); LOG.error("Triage failed: {}\nError: {}", status, message); APIResult result = new TriageResult(APIResult.Status.FAILED, message); - return new FalconWebException(Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); + return new FalconWebException(e, Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); } public static FalconWebException newInstanceSummaryException(Throwable e, Response.Status status) { String message = getMessage(e); LOG.error("Action failed: {}\nError: {}", status, message); APIResult result = new InstancesSummaryResult(APIResult.Status.FAILED, message); - return new FalconWebException(Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); + return new FalconWebException(e, Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); } public static FalconWebException newInstanceDependencyResult(Throwable e, Response.Status status) { - String message = getMessage(e); - LOG.error("Action failed: {}\nError: {}", status, message); - APIResult result = new InstanceDependencyResult(APIResult.Status.FAILED, message); - return new FalconWebException(Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); + return newInstanceDependencyResult(getMessage(e), status); } public static FalconWebException newInstanceDependencyResult(String message, Response.Status status) { LOG.error("Action failed: {}\nError: {}", status, message); APIResult result = new InstanceDependencyResult(APIResult.Status.FAILED, message); - return new FalconWebException(Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); + return new FalconWebException(new Exception(message), + Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); + } + + public static FalconWebException newException(String message, Response.Status status) { + APIResult result = new APIResult(APIResult.Status.FAILED, message); + return newException(result, status); } public static FalconWebException newException(APIResult result, Response.Status status) { LOG.error("Action failed: {}\nError: {}", status, result.getMessage()); - return new FalconWebException(Response.status(status). - entity(result).type(MediaType.TEXT_XML_TYPE).build()); + return new FalconWebException(new FalconException(result.getMessage()), + Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); } - public static FalconWebException newException(String message, Response.Status status) { - LOG.error("Action failed: {}\nError: {}", status, message); - APIResult result = new APIResult(APIResult.Status.FAILED, message); - return new FalconWebException(Response.status(status). - entity(result).type(MediaType.TEXT_XML_TYPE).build()); + public static FalconWebException newInstanceException(String message, Response.Status status) { + return newInstanceException(new FalconException(message), status); } - public static FalconWebException newInstanceException(String message, Response.Status status) { + public static FalconWebException newInstanceException(Throwable e, Response.Status status) { + LOG.error("Action failed: {}\nError: {}", status, e.getMessage()); + APIResult result = new InstancesResult(APIResult.Status.FAILED, e.getMessage()); + return new FalconWebException(e, Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); + } + + public static FalconWebException newMetadataResourceException(String message, Response.Status status) { LOG.error("Action failed: {}\nError: {}", status, message); - APIResult result = new InstancesResult(APIResult.Status.FAILED, message); - return new FalconWebException(Response.status(status).entity(result).type(MediaType.TEXT_XML_TYPE).build()); + // Using MediaType.TEXT_PLAIN for newMetadataResourceException to ensure backward compatibility. + return new FalconWebException(new Exception(message), + Response.status(status).entity(message).type(MediaType.TEXT_PLAIN).build()); } private static String getMessage(Throwable e) { @@ -106,7 +108,7 @@ public class FalconWebException extends WebApplicationException { return errors.toString(); } - public FalconWebException(Response response) { - super(response); + public FalconWebException(Throwable e, Response response) { + super(e, response); } } http://git-wip-us.apache.org/repos/asf/falcon/blob/e5a1d597/prism/src/main/java/org/apache/falcon/resource/metadata/AbstractMetadataResource.java ---------------------------------------------------------------------- diff --git a/prism/src/main/java/org/apache/falcon/resource/metadata/AbstractMetadataResource.java b/prism/src/main/java/org/apache/falcon/resource/metadata/AbstractMetadataResource.java index e9c90fc..762becb 100644 --- a/prism/src/main/java/org/apache/falcon/resource/metadata/AbstractMetadataResource.java +++ b/prism/src/main/java/org/apache/falcon/resource/metadata/AbstractMetadataResource.java @@ -19,14 +19,13 @@ package org.apache.falcon.resource.metadata; import com.tinkerpop.blueprints.Graph; +import org.apache.falcon.FalconWebException; import org.apache.falcon.metadata.MetadataMappingService; import org.apache.falcon.service.FalconService; import org.apache.falcon.service.Services; -import java.util.Set; - -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; +import java.util.Set; /** * A base class for managing Metadata operations. @@ -64,10 +63,8 @@ public abstract class AbstractMetadataResource { private void checkIfMetadataMappingServiceIsEnabled() { if (service == null) { - throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND) - .entity("Lineage " + MetadataMappingService.SERVICE_NAME + " is not enabled.") - .type("text/plain") - .build()); + throw FalconWebException.newMetadataResourceException( + "Lineage " + MetadataMappingService.SERVICE_NAME + " is not enabled.", Response.Status.NOT_FOUND); } } } http://git-wip-us.apache.org/repos/asf/falcon/blob/e5a1d597/prism/src/main/java/org/apache/falcon/resource/metadata/LineageMetadataResource.java ---------------------------------------------------------------------- diff --git a/prism/src/main/java/org/apache/falcon/resource/metadata/LineageMetadataResource.java b/prism/src/main/java/org/apache/falcon/resource/metadata/LineageMetadataResource.java index f8b503a..d595221 100644 --- a/prism/src/main/java/org/apache/falcon/resource/metadata/LineageMetadataResource.java +++ b/prism/src/main/java/org/apache/falcon/resource/metadata/LineageMetadataResource.java @@ -54,7 +54,6 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.ArrayList; @@ -182,8 +181,8 @@ public class LineageMetadataResource extends AbstractMetadataResource { if (vertex == null) { String message = "Vertex with [" + vertexId + "] cannot be found."; LOG.info(message); - throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND) - .entity(JSONObject.quote(message)).build()); + throw FalconWebException.newMetadataResourceException( + JSONObject.quote(message), Response.Status.NOT_FOUND); } return vertex; @@ -306,7 +305,8 @@ public class LineageMetadataResource extends AbstractMetadataResource { return Response.ok(response).build(); } catch (JSONException e) { - throw FalconWebException.newException(e, Response.Status.INTERNAL_SERVER_ERROR); + throw FalconWebException.newMetadataResourceException(e.getMessage(), + Response.Status.INTERNAL_SERVER_ERROR); } } @@ -331,7 +331,8 @@ public class LineageMetadataResource extends AbstractMetadataResource { return getVertexEdges(vertex, direction); } catch (JSONException e) { - throw FalconWebException.newException(e, Response.Status.INTERNAL_SERVER_ERROR); + throw FalconWebException.newMetadataResourceException(e.getMessage(), + Response.Status.INTERNAL_SERVER_ERROR); } } @@ -416,8 +417,8 @@ public class LineageMetadataResource extends AbstractMetadataResource { if (edge == null) { String message = "Edge with [" + edgeId + "] cannot be found."; LOG.info(message); - throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND) - .entity(JSONObject.quote(message)).build()); + throw FalconWebException.newMetadataResourceException( + JSONObject.quote(message), Response.Status.NOT_FOUND); } JSONObject response = new JSONObject(); @@ -500,10 +501,7 @@ public class LineageMetadataResource extends AbstractMetadataResource { private static void validateInputs(String errorMsg, String... inputs) { for (String input : inputs) { if (StringUtils.isEmpty(input)) { - throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) - .entity(errorMsg) - .type("text/plain") - .build()); + throw FalconWebException.newMetadataResourceException(errorMsg, Response.Status.BAD_REQUEST); } } } @@ -582,9 +580,8 @@ public class LineageMetadataResource extends AbstractMetadataResource { queryDirection = Direction.OUT; countOnly = false; } else { - throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) - .entity(JSONObject.quote(directionSegment + " segment was invalid.")) - .build()); + throw FalconWebException.newMetadataResourceException( + JSONObject.quote(directionSegment + " segment was invalid."), Response.Status.BAD_REQUEST); } } http://git-wip-us.apache.org/repos/asf/falcon/blob/e5a1d597/prism/src/main/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResource.java ---------------------------------------------------------------------- diff --git a/prism/src/main/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResource.java b/prism/src/main/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResource.java index 23a003a..220cc42 100644 --- a/prism/src/main/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResource.java +++ b/prism/src/main/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResource.java @@ -38,7 +38,6 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.Iterator; @@ -213,23 +212,22 @@ public class MetadataDiscoveryResource extends AbstractMetadataResource { private RelationshipType validateAndParseDimensionType(String type) { if (StringUtils.isEmpty(type) || type.contains("INSTANCE")) { - throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) - .entity("Invalid Dimension type : " + type).type("text/plain").build()); + throw FalconWebException.newMetadataResourceException( + "Invalid Dimension type : " + type, Response.Status.BAD_REQUEST); } try { return RelationshipType.valueOf(type); } catch (IllegalArgumentException iae) { - throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) - .entity("Invalid Dimension type : " + type).type("text/plain").build()); + throw FalconWebException.newMetadataResourceException( + "Invalid Dimension type : " + type, Response.Status.BAD_REQUEST); } } private void validateDimensionName(String name) { if (StringUtils.isEmpty(name)) { - throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) - .entity("Dimension name cannot be empty for Relations API").type("text/plain") - .build()); + throw FalconWebException.newMetadataResourceException( + "Dimension name cannot be empty for Relations API", Response.Status.BAD_REQUEST); } } } http://git-wip-us.apache.org/repos/asf/falcon/blob/e5a1d597/prism/src/test/java/org/apache/falcon/resource/metadata/LineageMetadataResourceTest.java ---------------------------------------------------------------------- diff --git a/prism/src/test/java/org/apache/falcon/resource/metadata/LineageMetadataResourceTest.java b/prism/src/test/java/org/apache/falcon/resource/metadata/LineageMetadataResourceTest.java index ac0e51f..fb4ff6f 100644 --- a/prism/src/test/java/org/apache/falcon/resource/metadata/LineageMetadataResourceTest.java +++ b/prism/src/test/java/org/apache/falcon/resource/metadata/LineageMetadataResourceTest.java @@ -22,6 +22,7 @@ import com.tinkerpop.blueprints.Direction; import com.tinkerpop.blueprints.Edge; import com.tinkerpop.blueprints.Graph; import com.tinkerpop.blueprints.Vertex; +import org.apache.falcon.FalconWebException; import org.apache.falcon.metadata.RelationshipLabel; import org.apache.falcon.metadata.RelationshipProperty; import org.apache.falcon.service.Services; @@ -33,7 +34,6 @@ import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import java.io.File; import java.io.FileFilter; @@ -60,7 +60,7 @@ public class LineageMetadataResourceTest { testContext.tearDown(); } - @Test (expectedExceptions = WebApplicationException.class) + @Test (expectedExceptions = FalconWebException.class) public void testGetVerticesWithInvalidId() throws Exception { LineageMetadataResource resource = new LineageMetadataResource(); Response response = resource.getVertex("blah"); @@ -156,7 +156,7 @@ public class LineageMetadataResourceTest { LineageMetadataResource resource = new LineageMetadataResource(); try { resource.getVertices(null, null); - } catch(WebApplicationException e) { + } catch(FalconWebException e) { Assert.assertEquals(e.getResponse().getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); Assert.assertEquals(e.getResponse().getEntity().toString(), "Invalid argument: key or value passed is null or empty."); @@ -221,7 +221,7 @@ public class LineageMetadataResourceTest { verifyVertexEdgesCount(vertexId, LineageMetadataResource.BOTH_IDS, expectedSize); } - @Test (expectedExceptions = WebApplicationException.class) + @Test (expectedExceptions = FalconWebException.class) public void testVertexEdgesForIdAndInvalidDirection() throws Exception { LineageMetadataResource resource = new LineageMetadataResource(); resource.getVertexEdges("0", "blah"); @@ -257,7 +257,7 @@ public class LineageMetadataResourceTest { Assert.assertEquals(totalSize, expectedSize); } - @Test (expectedExceptions = WebApplicationException.class) + @Test (expectedExceptions = FalconWebException.class) public void testEdgesByInvalidId() throws Exception { LineageMetadataResource resource = new LineageMetadataResource(); Response response = resource.getEdge("blah"); @@ -309,7 +309,7 @@ public class LineageMetadataResourceTest { Assert.assertEquals(totalSize, getEdgesCount(resource.getGraph())); } - @Test (expectedExceptions = WebApplicationException.class) + @Test (expectedExceptions = FalconWebException.class) public void testSerializeGraphBadFile() throws Exception { String path = StartupProperties.get().getProperty("falcon.graph.serialize.path"); StartupProperties.get().setProperty("falcon.graph.serialize.path", "blah"); @@ -339,7 +339,7 @@ public class LineageMetadataResourceTest { Assert.assertTrue(jsonFiles.length > 0); } - @Test (expectedExceptions = WebApplicationException.class) + @Test (expectedExceptions = FalconWebException.class) public void testLineageServiceIsDisabled() throws Exception { Services.get().reset(); try { http://git-wip-us.apache.org/repos/asf/falcon/blob/e5a1d597/prism/src/test/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResourceTest.java ---------------------------------------------------------------------- diff --git a/prism/src/test/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResourceTest.java b/prism/src/test/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResourceTest.java index 14f6e73..84ada9a 100644 --- a/prism/src/test/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResourceTest.java +++ b/prism/src/test/java/org/apache/falcon/resource/metadata/MetadataDiscoveryResourceTest.java @@ -18,6 +18,7 @@ package org.apache.falcon.resource.metadata; +import org.apache.falcon.FalconWebException; import org.apache.falcon.metadata.RelationshipType; import org.json.simple.JSONValue; import org.testng.Assert; @@ -25,7 +26,6 @@ import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import java.util.List; import java.util.Map; @@ -150,19 +150,19 @@ public class MetadataDiscoveryResourceTest { Assert.assertEquals(Integer.parseInt(results.get(MetadataDiscoveryResource.TOTAL_SIZE).toString()), 0); } - @Test(expectedExceptions = WebApplicationException.class) + @Test(expectedExceptions = FalconWebException.class) public void testListInvalidDimensionType() throws Exception { MetadataDiscoveryResource resource = new MetadataDiscoveryResource(); resource.listDimensionValues("INVALID", null); } - @Test(expectedExceptions = WebApplicationException.class) + @Test(expectedExceptions = FalconWebException.class) public void testListFeedDimensionType() throws Exception { MetadataDiscoveryResource resource = new MetadataDiscoveryResource(); resource.listDimensionValues("Feed", null); } - @Test(expectedExceptions = WebApplicationException.class) + @Test(expectedExceptions = FalconWebException.class) public void testListInstanceDimensionType() throws Exception { MetadataDiscoveryResource resource = new MetadataDiscoveryResource(); resource.listDimensionValues("FEED_INSTANCE", null); @@ -280,24 +280,24 @@ public class MetadataDiscoveryResourceTest { } - @Test(expectedExceptions = WebApplicationException.class) + @Test(expectedExceptions = FalconWebException.class) public void testEntityRelationsInvalidType() { MetadataDiscoveryResource resource = new MetadataDiscoveryResource(); resource.getDimensionRelations("INVALID", "name"); } - @Test(expectedExceptions = WebApplicationException.class) + @Test(expectedExceptions = FalconWebException.class) public void testEntityRelationsFeedType() throws Exception { MetadataDiscoveryResource resource = new MetadataDiscoveryResource(); resource.getDimensionRelations("FEED", "name"); } - @Test(expectedExceptions = WebApplicationException.class) + @Test(expectedExceptions = FalconWebException.class) public void testEntityRelationsInstanceType() throws Exception { MetadataDiscoveryResource resource = new MetadataDiscoveryResource(); resource.getDimensionRelations("FEED_INSTANCE", "name"); } - @Test(expectedExceptions = WebApplicationException.class) + @Test(expectedExceptions = FalconWebException.class) public void testEntityRelationsNoName() throws Exception { MetadataDiscoveryResource resource = new MetadataDiscoveryResource(); resource.getDimensionRelations(RelationshipType.TAGS.toString(), null); http://git-wip-us.apache.org/repos/asf/falcon/blob/e5a1d597/webapp/src/test/java/org/apache/falcon/resource/ProcessInstanceManagerIT.java ---------------------------------------------------------------------- diff --git a/webapp/src/test/java/org/apache/falcon/resource/ProcessInstanceManagerIT.java b/webapp/src/test/java/org/apache/falcon/resource/ProcessInstanceManagerIT.java index 2696e1e..d13caae 100644 --- a/webapp/src/test/java/org/apache/falcon/resource/ProcessInstanceManagerIT.java +++ b/webapp/src/test/java/org/apache/falcon/resource/ProcessInstanceManagerIT.java @@ -163,6 +163,13 @@ public class ProcessInstanceManagerIT { Assert.assertEquals(response.getInstances().length, 1); assertInstance(response.getInstances()[0], START_INSTANCE, WorkflowStatus.KILLED); + response = context.service.path("api/instance/kill/process/" + context.processName) + .header("Cookie", context.getAuthenticationToken()) + .accept(MediaType.APPLICATION_JSON) + .post(InstancesResult.class); + Assert.assertEquals(response.getStatus(), APIResult.Status.FAILED); + Assert.assertNotNull(response.getMessage()); + response = context.service.path("api/instance/status/process/" + context.processName) .queryParam("orderBy", "startTime").queryParam("filterBy", "STATUS:KILLED") .queryParam("start", START_INSTANCE)
