asterixdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From amo...@apache.org
Subject [2/2] asterixdb git commit: Use Chunked Http Response
Date Thu, 02 Feb 2017 00:28:27 GMT
Use Chunked Http Response

Change-Id: I249180f58e92058dd3b264ea17c4196b4baf4348
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1474
Sonar-Qube: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Michael Blow <mblow@apache.org>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
BAD: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/088991c5
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/088991c5
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/088991c5

Branch: refs/heads/master
Commit: 088991c5124b5da5e29c22e513942a369d1b6973
Parents: c7a8fa5
Author: Abdullah Alamoudi <bamousaa@gmail.com>
Authored: Tue Jan 31 14:40:03 2017 -0800
Committer: abdullah alamoudi <bamousaa@gmail.com>
Committed: Wed Feb 1 16:27:29 2017 -0800

----------------------------------------------------------------------
 .../asterix/api/http/server/ApiServlet.java     |  15 +--
 .../api/http/server/ClusterApiServlet.java      |   9 +-
 .../ClusterControllerDetailsApiServlet.java     |  12 +--
 .../api/http/server/ConnectorApiServlet.java    |  13 +--
 .../asterix/api/http/server/DdlApiServlet.java  |   2 +-
 .../api/http/server/DiagnosticsApiServlet.java  |  12 ++-
 .../asterix/api/http/server/FeedServlet.java    |  13 +--
 .../asterix/api/http/server/FullApiServlet.java |   2 +-
 .../server/NodeControllerDetailsApiServlet.java |  17 ++-
 .../api/http/server/QueryApiServlet.java        |   2 +-
 .../api/http/server/QueryResultApiServlet.java  |   9 +-
 .../api/http/server/QueryServiceServlet.java    |  20 ++--
 .../api/http/server/QueryStatusApiServlet.java  |   9 +-
 .../http/server/QueryWebInterfaceServlet.java   |  13 +--
 .../asterix/api/http/server/RestApiServlet.java | 107 +++++++++----------
 .../api/http/server/ShutdownApiServlet.java     |  10 +-
 .../api/http/server/UpdateApiServlet.java       |   2 +-
 .../api/http/server/VersionApiServlet.java      |   9 +-
 .../bootstrap/CCApplicationEntryPoint.java      |   2 +-
 .../api/http/servlet/ConnectorApiLetTest.java   |   4 +-
 .../api/http/servlet/VersionApiLetTest.java     |   4 +-
 .../org/apache/hyracks/http/api/IServlet.java   |  92 ++++++++++++++++
 .../hyracks/http/api/IServletRequest.java       |  59 ++++++++++
 .../hyracks/http/api/IServletResponse.java      |  85 +++++++++++++++
 .../hyracks/http/server/AbstractServlet.java    |   3 +
 .../http/server/ChunkedNettyOutputStream.java   |  69 ++++++++----
 .../hyracks/http/server/ChunkedResponse.java    |  92 +++++++++++++---
 .../hyracks/http/server/FullResponse.java       |  10 +-
 .../apache/hyracks/http/server/GetRequest.java  |   6 +-
 .../hyracks/http/server/HttpRequestHandler.java |  84 +++++++++++++++
 .../apache/hyracks/http/server/HttpServer.java  |  34 ++++--
 .../hyracks/http/server/HttpServerHandler.java  |  95 +++++-----------
 .../http/server/HttpServerInitializer.java      |  12 ++-
 .../apache/hyracks/http/server/IServlet.java    |  92 ----------------
 .../hyracks/http/server/IServletRequest.java    |  63 -----------
 .../hyracks/http/server/IServletResponse.java   |  77 -------------
 .../apache/hyracks/http/server/PostRequest.java |   5 +-
 .../hyracks/http/server/util/ServletUtils.java  | 107 +++++++++++++++++++
 38 files changed, 771 insertions(+), 500 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
index c38e0a9..ab05f10 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
@@ -52,10 +52,11 @@ import org.apache.asterix.translator.SessionConfig.OutputFormat;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.apache.hyracks.api.dataset.IHyracksDataset;
 import org.apache.hyracks.client.dataset.HyracksDataset;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import io.netty.handler.codec.http.HttpMethod;
 import io.netty.handler.codec.http.HttpResponseStatus;
@@ -107,7 +108,7 @@ public class ApiServlet extends AbstractServlet {
         String printJob = request.getParameter("print-job");
         String executeQuery = request.getParameter("execute-query");
         try {
-            IServletResponse.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
+            ServletUtils.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
         } catch (IOException e) {
             LOGGER.log(Level.WARNING, "Failure setting content type", e);
             response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
@@ -158,7 +159,7 @@ public class ApiServlet extends AbstractServlet {
 
         if ("/".equals(requestURI)) {
             try {
-                IServletResponse.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
+                ServletUtils.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
             } catch (IOException e) {
                 LOGGER.log(Level.WARNING, "Failure setting content type", e);
                 response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
@@ -177,7 +178,7 @@ public class ApiServlet extends AbstractServlet {
             // Special handler for font files and .png resources
             if (resourcePath.endsWith(".png")) {
                 BufferedImage img = ImageIO.read(is);
-                IServletResponse.setContentType(response, IServlet.ContentType.IMG_PNG);
+                ServletUtils.setContentType(response, IServlet.ContentType.IMG_PNG);
                 OutputStream outputStream = response.outputStream();
                 String formatName = "png";
                 ImageIO.write(img, formatName, outputStream);
@@ -185,7 +186,7 @@ public class ApiServlet extends AbstractServlet {
                 return;
             }
             String type = IServlet.ContentType.mime(QueryWebInterfaceServlet.extension(resourcePath));
-            IServletResponse.setContentType(response, "".equals(type) ? IServlet.ContentType.TEXT_PLAIN : type,
+            ServletUtils.setContentType(response, "".equals(type) ? IServlet.ContentType.TEXT_PLAIN : type,
                     IServlet.Encoding.UTF8);
             writeOutput(response, is, resourcePath);
         } catch (IOException e) {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java
index 6fd6c47..038ed2f 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterApiServlet.java
@@ -32,10 +32,11 @@ import org.apache.asterix.common.config.AbstractProperties;
 import org.apache.asterix.common.config.ReplicationProperties;
 import org.apache.asterix.common.utils.JSONUtil;
 import org.apache.asterix.runtime.util.ClusterStateManager;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -66,7 +67,7 @@ public class ClusterApiServlet extends AbstractServlet {
     }
 
     protected void getUnsafe(IServletRequest request, IServletResponse response) throws IOException {
-        IServletResponse.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
+        ServletUtils.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
         PrintWriter responseWriter = response.writer();
         try {
             ObjectNode json;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterControllerDetailsApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterControllerDetailsApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterControllerDetailsApiServlet.java
index 4419e8a..3d9167e 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterControllerDetailsApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ClusterControllerDetailsApiServlet.java
@@ -27,9 +27,10 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -57,7 +58,7 @@ public class ClusterControllerDetailsApiServlet extends ClusterApiServlet {
             } else {
                 json = processNode(request, hcc);
             }
-            IServletResponse.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
+            ServletUtils.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
             responseWriter.write(new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(json));
         } catch (IllegalArgumentException e) { // NOSONAR - exception not logged or rethrown
             response.setStatus(HttpResponseStatus.NOT_FOUND);
@@ -69,8 +70,7 @@ public class ClusterControllerDetailsApiServlet extends ClusterApiServlet {
         responseWriter.flush();
     }
 
-    private ObjectNode processNode(IServletRequest request, IHyracksClientConnection hcc)
-            throws Exception {
+    private ObjectNode processNode(IServletRequest request, IHyracksClientConnection hcc) throws Exception {
         String pathInfo = path(request);
         if (pathInfo.endsWith("/")) {
             throw new IllegalArgumentException();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ConnectorApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ConnectorApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ConnectorApiServlet.java
index d832672..caa00f1 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ConnectorApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ConnectorApiServlet.java
@@ -38,10 +38,11 @@ import org.apache.asterix.util.FlushDatasetUtils;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.apache.hyracks.api.client.NodeControllerInfo;
 import org.apache.hyracks.api.io.FileSplit;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -71,7 +72,7 @@ public class ConnectorApiServlet extends AbstractServlet {
         }
         response.setStatus(HttpResponseStatus.OK);
         try {
-            IServletResponse.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
+            ServletUtils.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
         } catch (IOException e) {
             LOGGER.log(Level.WARNING, "Failure setting content type", e);
             response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
@@ -107,8 +108,8 @@ public class ConnectorApiServlet extends AbstractServlet {
                 return;
             }
             boolean temp = dataset.getDatasetDetails().isTemp();
-            FileSplit[] fileSplits = metadataProvider.splitsForDataset(mdTxnCtx, dataverseName, datasetName,
-                    datasetName, temp);
+            FileSplit[] fileSplits =
+                    metadataProvider.splitsForDataset(mdTxnCtx, dataverseName, datasetName, datasetName, temp);
             ARecordType recordType = (ARecordType) metadataProvider.findType(dataset.getItemTypeDataverseName(),
                     dataset.getItemTypeName());
             List<List<String>> primaryKeys = DatasetUtils.getPartitioningKeys(dataset);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DdlApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DdlApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DdlApiServlet.java
index bcc6914..be6e280 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DdlApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DdlApiServlet.java
@@ -23,7 +23,7 @@ import java.util.concurrent.ConcurrentMap;
 import org.apache.asterix.compiler.provider.ILangCompilationProvider;
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.translator.IStatementExecutorFactory;
-import org.apache.hyracks.http.server.IServletRequest;
+import org.apache.hyracks.http.api.IServletRequest;
 
 public class DdlApiServlet extends RestApiServlet {
     private static final byte ALLOWED_CATEGORIES =

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DiagnosticsApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DiagnosticsApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DiagnosticsApiServlet.java
index d91352d..e6a32a3 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DiagnosticsApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/DiagnosticsApiServlet.java
@@ -37,9 +37,10 @@ import java.util.logging.Logger;
 import org.apache.asterix.api.http.servlet.ServletConstants;
 import org.apache.asterix.runtime.util.AppContextInfo;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
@@ -56,7 +57,7 @@ public class DiagnosticsApiServlet extends NodeControllerDetailsApiServlet {
 
     @Override
     protected void getUnsafe(IServletRequest request, IServletResponse response) throws IOException {
-        IServletResponse.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
+        ServletUtils.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
         PrintWriter responseWriter = response.writer();
         ObjectNode json;
         ObjectMapper om = new ObjectMapper();
@@ -95,7 +96,8 @@ public class DiagnosticsApiServlet extends NodeControllerDetailsApiServlet {
         Map<String, Map<String, Future<ObjectNode>>> ncDataMap = new HashMap<>();
         for (String nc : AppContextInfo.INSTANCE.getMetadataProperties().getNodeNames()) {
             Map<String, Future<ObjectNode>> ncData = new HashMap<>();
-            ncData.put("threaddump", executor.submit(() -> fixupKeys((ObjectNode) om.readTree(hcc.getThreadDump(nc)))));
+            ncData.put("threaddump",
+                    executor.submit(() -> fixupKeys((ObjectNode) om.readTree(hcc.getThreadDump(nc)))));
             ncData.put("config", executor
                     .submit(() -> fixupKeys((ObjectNode) om.readTree(hcc.getNodeDetailsJSON(nc, false, true)))));
             ncData.put("stats", executor.submit(() -> fixupKeys(processNodeStats(hcc, nc))));

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FeedServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FeedServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FeedServlet.java
index ac79088..7fe7370 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FeedServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FeedServlet.java
@@ -31,10 +31,11 @@ import java.util.logging.Logger;
 
 import javax.imageio.ImageIO;
 
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import io.netty.handler.codec.http.HttpResponseStatus;
 
@@ -53,7 +54,7 @@ public class FeedServlet extends AbstractServlet {
             String requestURI = request.getHttpRequest().uri();
 
             if ("/".equals(requestURI)) {
-                IServletResponse.setContentType(response, IServlet.ContentType.TEXT_HTML);
+                ServletUtils.setContentType(response, IServlet.ContentType.TEXT_HTML);
                 resourcePath = "/feed/home.html";
             } else {
                 resourcePath = requestURI;
@@ -71,12 +72,12 @@ public class FeedServlet extends AbstractServlet {
                 BufferedImage img = ImageIO.read(is);
                 OutputStream outputStream = response.outputStream();
                 String formatName = "png";
-                IServletResponse.setContentType(response, IServlet.ContentType.IMG_PNG);
+                ServletUtils.setContentType(response, IServlet.ContentType.IMG_PNG);
                 ImageIO.write(img, formatName, outputStream);
                 return;
             }
 
-            IServletResponse.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
+            ServletUtils.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
             InputStreamReader isr = new InputStreamReader(is);
             StringBuilder sb = new StringBuilder();
             BufferedReader br = new BufferedReader(isr);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FullApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FullApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FullApiServlet.java
index 7788136..9c08fbd 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FullApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/FullApiServlet.java
@@ -23,7 +23,7 @@ import java.util.concurrent.ConcurrentMap;
 import org.apache.asterix.compiler.provider.ILangCompilationProvider;
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.translator.IStatementExecutorFactory;
-import org.apache.hyracks.http.server.IServletRequest;
+import org.apache.hyracks.http.api.IServletRequest;
 
 public class FullApiServlet extends RestApiServlet {
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NodeControllerDetailsApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NodeControllerDetailsApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NodeControllerDetailsApiServlet.java
index c1423e7..2dbaa54 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NodeControllerDetailsApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NodeControllerDetailsApiServlet.java
@@ -31,9 +31,10 @@ import java.util.logging.Logger;
 
 import org.apache.asterix.runtime.util.ClusterStateManager;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -66,7 +67,7 @@ public class NodeControllerDetailsApiServlet extends ClusterApiServlet {
             } else {
                 json = processNode(request, hcc);
             }
-            IServletResponse.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
+            ServletUtils.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
             responseWriter.write(om.writerWithDefaultPrettyPrinter().writeValueAsString(json));
         } catch (IllegalStateException e) { // NOSONAR - exception not logged or rethrown
             response.setStatus(HttpResponseStatus.SERVICE_UNAVAILABLE);
@@ -80,8 +81,7 @@ public class NodeControllerDetailsApiServlet extends ClusterApiServlet {
         responseWriter.flush();
     }
 
-    private ObjectNode processNode(IServletRequest request, IHyracksClientConnection hcc)
-            throws Exception {
+    private ObjectNode processNode(IServletRequest request, IHyracksClientConnection hcc) throws Exception {
         String pathInfo = path(request);
         if (pathInfo.endsWith("/")) {
             throw new IllegalArgumentException();
@@ -172,7 +172,7 @@ public class NodeControllerDetailsApiServlet extends ClusterApiServlet {
                     }
                     final JsonNode value = valueArray.get(index);
                     json.remove(key);
-                    json.set(key.replaceAll("s$",""), value);
+                    json.set(key.replaceAll("s$", ""), value);
                 }
             }
         }
@@ -205,8 +205,7 @@ public class NodeControllerDetailsApiServlet extends ClusterApiServlet {
         String dump = hcc.getThreadDump(node);
         if (dump == null) {
             // check to see if this is a node that is simply down
-            throw ClusterStateManager.INSTANCE.getNodePartitions(node) != null
-                    ? new IllegalStateException()
+            throw ClusterStateManager.INSTANCE.getNodePartitions(node) != null ? new IllegalStateException()
                     : new IllegalArgumentException();
         }
         return (ObjectNode) om.readTree(dump);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryApiServlet.java
index 917d9a8..160c801 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryApiServlet.java
@@ -23,7 +23,7 @@ import java.util.concurrent.ConcurrentMap;
 import org.apache.asterix.compiler.provider.ILangCompilationProvider;
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.translator.IStatementExecutorFactory;
-import org.apache.hyracks.http.server.IServletRequest;
+import org.apache.hyracks.http.api.IServletRequest;
 
 public class QueryApiServlet extends RestApiServlet {
     private static final byte ALLOWED_CATEGORIES = Statement.Category.QUERY;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
index 6240f51..06ddf44 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
@@ -39,10 +39,11 @@ import org.apache.hyracks.api.dataset.IHyracksDataset;
 import org.apache.hyracks.api.dataset.ResultSetId;
 import org.apache.hyracks.api.job.JobId;
 import org.apache.hyracks.client.dataset.HyracksDataset;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -67,7 +68,7 @@ public class QueryResultApiServlet extends AbstractServlet {
         response.setStatus(HttpResponseStatus.OK);
         // TODO this seems wrong ...
         try {
-            IServletResponse.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
+            ServletUtils.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
         } catch (IOException e) {
             LOGGER.log(Level.WARNING, "Failure setting content type", e);
             response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index b302bab..43530ea 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
@@ -53,10 +53,11 @@ import org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendab
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.apache.hyracks.api.dataset.IHyracksDataset;
 import org.apache.hyracks.client.dataset.HyracksDataset;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -74,8 +75,7 @@ public class QueryServiceServlet extends AbstractServlet {
     private final IStatementExecutorFactory statementExecutorFactory;
 
     public QueryServiceServlet(ConcurrentMap<String, Object> ctx, String[] paths,
-            ILangCompilationProvider compilationProvider,
-            IStatementExecutorFactory statementExecutorFactory) {
+            ILangCompilationProvider compilationProvider, IStatementExecutorFactory statementExecutorFactory) {
         super(ctx, paths);
         this.compilationProvider = compilationProvider;
         this.statementExecutorFactory = statementExecutorFactory;
@@ -325,8 +325,8 @@ public class QueryServiceServlet extends AbstractServlet {
         SessionConfig.ResultDecorator handlePostfix = (AlgebricksAppendable app) -> app.append(",\n");
 
         SessionConfig.OutputFormat format = getFormat(param.format);
-        SessionConfig sessionConfig = new SessionConfig(resultWriter, format, resultPrefix, resultPostfix,
-                handlePrefix, handlePostfix);
+        SessionConfig sessionConfig =
+                new SessionConfig(resultWriter, format, resultPrefix, resultPostfix, handlePrefix, handlePostfix);
         sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, true);
         sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, param.pretty);
         sessionConfig.set(SessionConfig.FORMAT_QUOTE_RECORD,
@@ -482,7 +482,7 @@ public class QueryServiceServlet extends AbstractServlet {
         QueryTranslator.ResultDelivery delivery = parseResultDelivery(param.mode);
 
         SessionConfig sessionConfig = createSessionConfig(param, resultWriter);
-        IServletResponse.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
+        ServletUtils.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
 
         HttpResponseStatus status = HttpResponseStatus.OK;
         Stats stats = new Stats();
@@ -517,8 +517,8 @@ public class QueryServiceServlet extends AbstractServlet {
             IParser parser = compilationProvider.getParserFactory().createParser(param.statement);
             List<Statement> statements = parser.parse();
             MetadataManager.INSTANCE.init();
-            IStatementExecutor translator = statementExecutorFactory.create(statements, sessionConfig,
-                    compilationProvider);
+            IStatementExecutor translator =
+                    statementExecutorFactory.create(statements, sessionConfig, compilationProvider);
             execStart = System.nanoTime();
             translator.compileAndExecute(hcc, hds, delivery, stats);
             execEnd = System.nanoTime();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java
index 197a39c..039c740 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryStatusApiServlet.java
@@ -33,10 +33,11 @@ import org.apache.hyracks.api.dataset.IHyracksDataset;
 import org.apache.hyracks.api.dataset.ResultSetId;
 import org.apache.hyracks.api.job.JobId;
 import org.apache.hyracks.client.dataset.HyracksDataset;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -60,7 +61,7 @@ public class QueryStatusApiServlet extends AbstractServlet {
         }
         response.setStatus(HttpResponseStatus.OK);
         try {
-            IServletResponse.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
+            ServletUtils.setContentType(response, IServlet.ContentType.TEXT_HTML, IServlet.Encoding.UTF8);
         } catch (IOException e) {
             LOGGER.log(Level.WARNING, "Failure setting content type", e);
             response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java
index d924cf1..fac5883 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java
@@ -29,10 +29,11 @@ import java.util.logging.Logger;
 import org.apache.asterix.common.config.ExternalProperties;
 import org.apache.asterix.runtime.util.AppContextInfo;
 import org.apache.commons.io.IOUtils;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -70,7 +71,7 @@ public class QueryWebInterfaceServlet extends AbstractServlet {
         response.setStatus(HttpResponseStatus.OK);
 
         if ("/".equals(requestURI)) {
-            IServletResponse.setContentType(response, IServlet.ContentType.TEXT_HTML);
+            ServletUtils.setContentType(response, IServlet.ContentType.TEXT_HTML);
             resourcePath = "/queryui/queryui.html";
         } else {
             resourcePath = requestURI;
@@ -87,7 +88,7 @@ public class QueryWebInterfaceServlet extends AbstractServlet {
                 String mime = IServlet.ContentType.mime(extension);
                 if (mime != null) {
                     OutputStream out = response.outputStream();
-                    IServletResponse.setContentType(response, mime);
+                    ServletUtils.setContentType(response, mime);
                     try {
                         IOUtils.copy(is, out);
                     } catch (Exception e) {
@@ -106,7 +107,7 @@ public class QueryWebInterfaceServlet extends AbstractServlet {
     }
 
     private void doPost(IServletResponse response) throws IOException {
-        IServletResponse.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
+        ServletUtils.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
         ExternalProperties externalProperties = AppContextInfo.INSTANCE.getExternalProperties();
         response.setStatus(HttpResponseStatus.OK);
         ObjectMapper om = new ObjectMapper();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
index c2d1d33..787ff47 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/RestApiServlet.java
@@ -40,6 +40,7 @@ import org.apache.asterix.lang.common.base.IParserFactory;
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.metadata.MetadataManager;
 import org.apache.asterix.translator.IStatementExecutor;
+import org.apache.asterix.translator.IStatementExecutor.ResultDelivery;
 import org.apache.asterix.translator.IStatementExecutorFactory;
 import org.apache.asterix.translator.SessionConfig;
 import org.apache.asterix.translator.SessionConfig.OutputFormat;
@@ -47,11 +48,13 @@ import org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendab
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 import org.apache.hyracks.api.dataset.IHyracksDataset;
 import org.apache.hyracks.client.dataset.HyracksDataset;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
@@ -78,17 +81,13 @@ public abstract class RestApiServlet extends AbstractServlet {
      * based on the Accept: header and other servlet parameters.
      */
     static SessionConfig initResponse(IServletRequest request, IServletResponse response) throws IOException {
-        IServletResponse.setContentType(response, IServlet.ContentType.TEXT_PLAIN, IServlet.Encoding.UTF8);
-
+        ServletUtils.setContentType(response, IServlet.ContentType.TEXT_PLAIN, IServlet.Encoding.UTF8);
         // CLEAN_JSON output is the default; most generally useful for a
         // programmatic HTTP API
         OutputFormat format = OutputFormat.CLEAN_JSON;
         // First check the "output" servlet parameter.
         String output = request.getParameter("output");
-        String accept = request.getHeader("Accept");
-        if (accept == null) {
-            accept = "";
-        }
+        String accept = request.getHeader("Accept", "");
         if (output != null) {
             if ("CSV".equals(output)) {
                 format = OutputFormat.CSV;
@@ -114,22 +113,12 @@ public abstract class RestApiServlet extends AbstractServlet {
         SessionConfig.ResultDecorator handlePrefix =
                 (AlgebricksAppendable app) -> app.append("{ \"").append("handle").append("\": ");
         SessionConfig.ResultDecorator handlePostfix = (AlgebricksAppendable app) -> app.append(" }");
-
         SessionConfig sessionConfig =
                 new SessionConfig(response.writer(), format, null, null, handlePrefix, handlePostfix);
 
         // If it's JSON or ADM, check for the "wrapper-array" flag. Default is
         // "true" for JSON and "false" for ADM. (Not applicable for CSV.)
-        boolean wrapperArray;
-        switch (format) {
-            case CLEAN_JSON:
-            case LOSSLESS_JSON:
-                wrapperArray = true;
-                break;
-            default:
-                wrapperArray = false;
-                break;
-        }
+        boolean wrapperArray = format == OutputFormat.CLEAN_JSON || format == OutputFormat.LOSSLESS_JSON;
         String wrapperParam = request.getParameter("wrapper-array");
         if (wrapperParam != null) {
             wrapperArray = Boolean.valueOf(wrapperParam);
@@ -142,22 +131,24 @@ public abstract class RestApiServlet extends AbstractServlet {
         // Now that format is set, output the content-type
         switch (format) {
             case ADM:
-                IServletResponse.setContentType(response, "application/x-adm");
+                ServletUtils.setContentType(response, "application/x-adm");
                 break;
             case CLEAN_JSON:
                 // No need to reflect "clean-ness" in output type; fall through
             case LOSSLESS_JSON:
-                IServletResponse.setContentType(response, "application/json");
+                ServletUtils.setContentType(response, "application/json");
                 break;
             case CSV:
                 // Check for header parameter or in Accept:.
                 if ("present".equals(request.getParameter("header")) || accept.contains("header=present")) {
-                    IServletResponse.setContentType(response, "text/csv; header=present");
+                    ServletUtils.setContentType(response, "text/csv; header=present");
                     sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, true);
                 } else {
-                    IServletResponse.setContentType(response, "text/csv; header=absent");
+                    ServletUtils.setContentType(response, "text/csv; header=absent");
                 }
                 break;
+            default:
+                throw new IOException("Unknown format " + format);
         }
         return sessionConfig;
     }
@@ -169,45 +160,49 @@ public abstract class RestApiServlet extends AbstractServlet {
             // enable cross-origin resource sharing
             response.setHeader("Access-Control-Allow-Origin", "*");
             response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
-
             SessionConfig sessionConfig = initResponse(request, response);
             QueryTranslator.ResultDelivery resultDelivery = whichResultDelivery(request);
-            try {
-                response.setStatus(HttpResponseStatus.OK);
-                IHyracksClientConnection hcc = (IHyracksClientConnection) ctx.get(HYRACKS_CONNECTION_ATTR);
-                IHyracksDataset hds = (IHyracksDataset) ctx.get(HYRACKS_DATASET_ATTR);
-                if (hds == null) {
-                    synchronized (ctx) {
-                        hds = (IHyracksDataset) ctx.get(HYRACKS_DATASET_ATTR);
-                        if (hds == null) {
-                            hds = new HyracksDataset(hcc, ResultReader.FRAME_SIZE, ResultReader.NUM_READERS);
-                            ctx.put(HYRACKS_DATASET_ATTR, hds);
-                        }
+            doHandle(response, query, sessionConfig, resultDelivery);
+        } catch (Exception e) {
+            response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
+            LOGGER.log(Level.WARNING, "Failure handling request", e);
+            return;
+        }
+    }
+
+    private void doHandle(IServletResponse response, String query, SessionConfig sessionConfig,
+            ResultDelivery resultDelivery) throws JsonProcessingException {
+        try {
+            response.setStatus(HttpResponseStatus.OK);
+            IHyracksClientConnection hcc = (IHyracksClientConnection) ctx.get(HYRACKS_CONNECTION_ATTR);
+            IHyracksDataset hds = (IHyracksDataset) ctx.get(HYRACKS_DATASET_ATTR);
+            if (hds == null) {
+                synchronized (ctx) {
+                    hds = (IHyracksDataset) ctx.get(HYRACKS_DATASET_ATTR);
+                    if (hds == null) {
+                        hds = new HyracksDataset(hcc, ResultReader.FRAME_SIZE, ResultReader.NUM_READERS);
+                        ctx.put(HYRACKS_DATASET_ATTR, hds);
                     }
                 }
-                IParser parser = parserFactory.createParser(query);
-                List<Statement> aqlStatements = parser.parse();
-                validate(aqlStatements);
-                MetadataManager.INSTANCE.init();
-                IStatementExecutor translator =
-                        statementExecutorFactory.create(aqlStatements, sessionConfig, compilationProvider);
-                translator.compileAndExecute(hcc, hds, resultDelivery);
-            } catch (AsterixException | TokenMgrError | org.apache.asterix.aqlplus.parser.TokenMgrError pe) {
-                GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, pe.getMessage(), pe);
-                String errorMessage = ResultUtil.buildParseExceptionMessage(pe, query);
-                ObjectNode errorResp =
-                        ResultUtil.getErrorResponse(2, errorMessage, "", ResultUtil.extractFullStackTrace(pe));
-                sessionConfig.out().write(new ObjectMapper().writeValueAsString(errorResp));
-                response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
-            } catch (Exception e) {
-                GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, e.getMessage(), e);
-                ResultUtil.apiErrorHandler(sessionConfig.out(), e);
-                response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
             }
+            IParser parser = parserFactory.createParser(query);
+            List<Statement> aqlStatements = parser.parse();
+            validate(aqlStatements);
+            MetadataManager.INSTANCE.init();
+            IStatementExecutor translator =
+                    statementExecutorFactory.create(aqlStatements, sessionConfig, compilationProvider);
+            translator.compileAndExecute(hcc, hds, resultDelivery);
+        } catch (AsterixException | TokenMgrError | org.apache.asterix.aqlplus.parser.TokenMgrError pe) {
+            response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
+            GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, pe.getMessage(), pe);
+            String errorMessage = ResultUtil.buildParseExceptionMessage(pe, query);
+            ObjectNode errorResp =
+                    ResultUtil.getErrorResponse(2, errorMessage, "", ResultUtil.extractFullStackTrace(pe));
+            sessionConfig.out().write(new ObjectMapper().writeValueAsString(errorResp));
         } catch (Exception e) {
-            LOGGER.log(Level.WARNING, "Failure handling request", e);
+            GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, e.getMessage(), e);
             response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
-            return;
+            ResultUtil.apiErrorHandler(sessionConfig.out(), e);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java
index 25be651..dc48288 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ShutdownApiServlet.java
@@ -30,10 +30,11 @@ import java.util.logging.Logger;
 import org.apache.asterix.common.config.GlobalConfig;
 import org.apache.asterix.runtime.util.ClusterStateManager;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -70,8 +71,7 @@ public class ShutdownApiServlet extends AbstractServlet {
         }, "Shutdown Servlet Worker");
 
         try {
-            IServletResponse.setContentType(response, IServlet.ContentType.APPLICATION_JSON,
-                    IServlet.Encoding.UTF8);
+            ServletUtils.setContentType(response, IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
         } catch (IOException e) {
             LOGGER.log(Level.WARNING, "Failure handling request", e);
             response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/UpdateApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/UpdateApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/UpdateApiServlet.java
index 1c173d2..0a0e680 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/UpdateApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/UpdateApiServlet.java
@@ -23,7 +23,7 @@ import java.util.concurrent.ConcurrentMap;
 import org.apache.asterix.compiler.provider.ILangCompilationProvider;
 import org.apache.asterix.lang.common.base.Statement;
 import org.apache.asterix.translator.IStatementExecutorFactory;
-import org.apache.hyracks.http.server.IServletRequest;
+import org.apache.hyracks.http.api.IServletRequest;
 
 public class UpdateApiServlet extends RestApiServlet {
     private static final byte ALLOWED_CATEGORIES = Statement.Category.QUERY | Statement.Category.UPDATE;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/VersionApiServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/VersionApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/VersionApiServlet.java
index e5ceccc..5899660 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/VersionApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/VersionApiServlet.java
@@ -28,10 +28,11 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.asterix.runtime.util.AppContextInfo;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.apache.hyracks.http.server.AbstractServlet;
-import org.apache.hyracks.http.server.IServlet;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -61,7 +62,7 @@ public class VersionApiServlet extends AbstractServlet {
             responseObject.put(e.getKey(), e.getValue());
         }
         try {
-            IServletResponse.setContentType(response, IServlet.ContentType.TEXT_PLAIN, IServlet.Encoding.UTF8);
+            ServletUtils.setContentType(response, IServlet.ContentType.TEXT_PLAIN, IServlet.Encoding.UTF8);
         } catch (IOException e) {
             LOGGER.log(Level.WARNING, "Failure handling request", e);
             response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
index 3a8852e..b17a722 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
@@ -72,8 +72,8 @@ import org.apache.hyracks.api.lifecycle.LifeCycleComponentManager;
 import org.apache.hyracks.api.messages.IMessageBroker;
 import org.apache.hyracks.control.cc.ClusterControllerService;
 import org.apache.hyracks.control.common.controllers.CCConfig;
+import org.apache.hyracks.http.api.IServlet;
 import org.apache.hyracks.http.server.HttpServer;
-import org.apache.hyracks.http.server.IServlet;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.eclipse.jetty.servlet.ServletMapping;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/ConnectorApiLetTest.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/ConnectorApiLetTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/ConnectorApiLetTest.java
index b1fdab5..d34a9cf 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/ConnectorApiLetTest.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/ConnectorApiLetTest.java
@@ -43,8 +43,8 @@ import org.apache.hyracks.api.client.NodeControllerInfo;
 import org.apache.hyracks.api.comm.NetworkAddress;
 import org.apache.hyracks.api.io.FileSplit;
 import org.apache.hyracks.api.io.ManagedFileSplit;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.junit.Assert;
 import org.junit.Test;
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/VersionApiLetTest.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/VersionApiLetTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/VersionApiLetTest.java
index 936b717..b482948 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/VersionApiLetTest.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/VersionApiLetTest.java
@@ -35,8 +35,8 @@ import org.apache.asterix.common.config.BuildProperties;
 import org.apache.asterix.runtime.util.AppContextInfo;
 import org.apache.asterix.test.runtime.SqlppExecutionTest;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.http.server.IServletRequest;
-import org.apache.hyracks.http.server.IServletResponse;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
 import org.junit.Assert;
 import org.junit.Test;
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServlet.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServlet.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServlet.java
new file mode 100644
index 0000000..b079d36
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServlet.java
@@ -0,0 +1,92 @@
+/*
+ * 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.hyracks.http.api;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Represents a component that handles IServLet requests
+ */
+public interface IServlet {
+
+    public class Encoding {
+        public static final String UTF8 = "utf-8";
+
+        private Encoding() {
+        }
+    }
+
+    public class ContentType {
+        public static final String APPLICATION_ADM = "application/x-adm";
+        public static final String APPLICATION_JSON = "application/json";
+        public static final String CSV = "text/csv";
+        public static final String IMG_PNG = "image/png";
+        public static final String TEXT_HTML = "text/html";
+        public static final String TEXT_PLAIN = "text/plain";
+
+        private ContentType() {
+        }
+
+        /**
+         * Get the mime string representation from the extension
+         * @param extension
+         * @return
+         */
+        public static String mime(String extension) {
+            switch (extension) {
+                case ".png":
+                    return "image/png";
+                case ".eot":
+                    return "application/vnd.ms-fontobject";
+                case ".svg":
+                    return "image/svg+xml\t";
+                case ".ttf":
+                    return "application/x-font-ttf";
+                case ".woff":
+                case ".woff2":
+                    return "application/x-font-woff";
+                case ".html":
+                    return "text/html";
+                case ".css":
+                    return "text/css";
+                case ".js":
+                    return "application/javascript";
+                default:
+                    return null;
+            }
+        }
+    }
+
+    /**
+     * @return an array of paths associated with this IServLet
+     */
+    String[] getPaths();
+
+    /**
+     * @return the context associated with this IServlet
+     */
+    ConcurrentMap<String, Object> ctx();
+
+    /**
+     * handle the IServLetRequest writing the response in the passed IServLetResponse
+     * @param request
+     * @param response
+     */
+    void handle(IServletRequest request, IServletResponse response);
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletRequest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletRequest.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletRequest.java
new file mode 100644
index 0000000..610c3d1
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletRequest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.hyracks.http.api;
+
+import io.netty.handler.codec.http.FullHttpRequest;
+
+/**
+ * An Http Request instance
+ */
+public interface IServletRequest {
+    /**
+     * @return the full http request
+     */
+    FullHttpRequest getHttpRequest();
+
+    /**
+     * Get a request parameter
+     *
+     * @param name
+     * @return the parameter or null if not found
+     */
+    String getParameter(CharSequence name);
+
+    /**
+     * Get a request header
+     *
+     * @param name
+     * @return the header or null if not found
+     */
+    String getHeader(CharSequence name);
+
+    /**
+     * Get a request header if found, return the default value, otherwise
+     *
+     * @param name
+     * @param defaultValue
+     * @return the header or defaultValue if not found
+     */
+    default String getHeader(CharSequence name, String defaultValue) {
+        String value = getHeader(name);
+        return value == null ? defaultValue : value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletResponse.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletResponse.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletResponse.java
new file mode 100644
index 0000000..1a7c65f
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/api/IServletResponse.java
@@ -0,0 +1,85 @@
+/*
+ * 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.hyracks.http.api;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import io.netty.channel.ChannelFuture;
+import io.netty.handler.codec.http.HttpResponseStatus;
+
+/**
+ * A response to an instance of IServletRequest
+ */
+public interface IServletResponse extends Closeable {
+
+    /**
+     * Set a response header
+     *
+     * @param name
+     *            the name of the header
+     * @param value
+     *            the value of the header
+     * @return
+     *         the servlet response with the header set
+     * @throws IOException
+     */
+    IServletResponse setHeader(CharSequence name, Object value) throws IOException;
+
+    /**
+     * Set the status of the http response
+     *
+     * @param status
+     */
+    void setStatus(HttpResponseStatus status);
+
+    /**
+     * Get the output writer for the response which writes to the response output stream
+     *
+     * @return the response writer
+     */
+    PrintWriter writer();
+
+    /**
+     * Get the output stream for the response
+     *
+     * @return the response output stream
+     */
+    OutputStream outputStream();
+
+    /**
+     * Get last content future
+     * Must only be called after the servlet response has been closed
+     * Used to listen to events about the last content sent through the network
+     * For example, to close the connection after the event has been completed
+     * lastContentFuture().addListener(ChannelFutureListener.CLOSE);
+     *
+     * @return
+     * @throws IOException
+     */
+    ChannelFuture lastContentFuture() throws IOException;
+
+    /**
+     * Notifies the response that the channel has become writable
+     * became writable or unwritable. Used for flow control
+     */
+    void notifyChannelWritable();
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
index 22bbc50..7d24994 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
@@ -20,6 +20,9 @@ package org.apache.hyracks.http.server;
 
 import java.util.concurrent.ConcurrentMap;
 
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+
 public abstract class AbstractServlet implements IServlet {
     protected final String[] paths;
     protected final ConcurrentMap<String, Object> ctx;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedNettyOutputStream.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedNettyOutputStream.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedNettyOutputStream.java
index 984122b..65cdd52 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedNettyOutputStream.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedNettyOutputStream.java
@@ -20,6 +20,8 @@ package org.apache.hyracks.http.server;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
@@ -28,26 +30,24 @@ import io.netty.handler.codec.http.HttpResponseStatus;
 
 public class ChunkedNettyOutputStream extends OutputStream {
 
+    private static final Logger LOGGER = Logger.getLogger(ChunkedNettyOutputStream.class.getName());
     private final ChannelHandlerContext ctx;
     private final ChunkedResponse response;
     private ByteBuf buffer;
 
-    public ChunkedNettyOutputStream(ChannelHandlerContext ctx, int chunkSize,
-            ChunkedResponse response) {
+    public ChunkedNettyOutputStream(ChannelHandlerContext ctx, int chunkSize, ChunkedResponse response) {
         this.response = response;
         this.ctx = ctx;
         buffer = ctx.alloc().buffer(chunkSize);
     }
 
     @Override
-    public synchronized void write(byte[] b, int off, int len) {
-        if ((off < 0) || (off > b.length) || (len < 0) ||
-                ((off + len) > b.length)) {
+    public void write(byte[] b, int off, int len) throws IOException {
+        if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length)) {
             throw new IndexOutOfBoundsException();
         } else if (len == 0) {
             return;
         }
-
         if (len > buffer.capacity()) {
             flush();
             flush(b, off, len);
@@ -64,45 +64,68 @@ public class ChunkedNettyOutputStream extends OutputStream {
     }
 
     @Override
-    public synchronized void write(int b) {
-        if (buffer.writableBytes() > 0) {
-            buffer.writeByte(b);
-        } else {
+    public void write(int b) throws IOException {
+        if (!buffer.isWritable()) {
             flush();
-            buffer.writeByte(b);
         }
+        buffer.writeByte(b);
     }
 
     @Override
-    public synchronized void close() throws IOException {
-        flush();
-        buffer.release();
+    public void close() throws IOException {
+        if (response.isHeaderSent() || response.status() != HttpResponseStatus.OK) {
+            flush();
+            buffer.release();
+        } else {
+            response.fullReponse(buffer);
+        }
         super.close();
     }
 
     @Override
-    public synchronized void flush() {
+    public void flush() throws IOException {
+        ensureWritable();
         if (buffer.readableBytes() > 0) {
-            int size = buffer.capacity();
             if (response.status() == HttpResponseStatus.OK) {
-                response.flush();
+                int size = buffer.capacity();
+                response.beforeFlush();
                 DefaultHttpContent content = new DefaultHttpContent(buffer);
-                ctx.write(content);
+                ctx.write(content, ctx.channel().voidPromise());
+                buffer = ctx.alloc().buffer(size);
             } else {
-                response.error(buffer);
+                ByteBuf aBuffer = ctx.alloc().buffer(buffer.readableBytes());
+                aBuffer.writeBytes(buffer);
+                response.error(aBuffer);
             }
-            buffer = ctx.alloc().buffer(size);
         }
     }
 
-    private synchronized void flush(byte[] buf, int offset, int len) {
+    private void flush(byte[] buf, int offset, int len) throws IOException {
+        ensureWritable();
         ByteBuf aBuffer = ctx.alloc().buffer(len);
         aBuffer.writeBytes(buf, offset, len);
         if (response.status() == HttpResponseStatus.OK) {
-            response.flush();
-            ctx.write(new DefaultHttpContent(aBuffer));
+            response.beforeFlush();
+            ctx.write(new DefaultHttpContent(aBuffer), ctx.channel().voidPromise());
         } else {
             response.error(aBuffer);
         }
     }
+
+    private synchronized void ensureWritable() throws IOException {
+        while (!ctx.channel().isWritable()) {
+            try {
+                ctx.flush();
+                wait();
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                LOGGER.log(Level.WARNING, "Interupted while waiting for channel to be writable", e);
+                throw new IOException(e);
+            }
+        }
+    }
+
+    public synchronized void resume() {
+        notifyAll();
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedResponse.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedResponse.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedResponse.java
index 19c2664..cb0cd80 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedResponse.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/ChunkedResponse.java
@@ -18,25 +18,44 @@
  */
 package org.apache.hyracks.http.server;
 
-import static io.netty.handler.codec.http.HttpResponseStatus.OK;
-import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
-
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 
+import org.apache.hyracks.http.api.IServletResponse;
+
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
 import io.netty.handler.codec.http.DefaultHttpResponse;
 import io.netty.handler.codec.http.FullHttpRequest;
 import io.netty.handler.codec.http.HttpHeaderNames;
 import io.netty.handler.codec.http.HttpHeaderValues;
+import io.netty.handler.codec.http.HttpHeaders;
 import io.netty.handler.codec.http.HttpResponse;
 import io.netty.handler.codec.http.HttpResponseStatus;
 import io.netty.handler.codec.http.HttpUtil;
+import io.netty.handler.codec.http.HttpVersion;
 import io.netty.handler.codec.http.LastHttpContent;
 
+/**
+ * A chunked http response. Here is how it is expected to work:
+ * If the response is a success aka 200 and is less than chunkSize, then it is sent as a single http response message
+ * If the response is larger than the chunkSize and the response status is 200, then it is sent as chunks of chunkSize.
+ * If the response status is non 200, then it is always sent as a single http response message.
+ * If the response status is non 200, then output buffered before setting the response status is discarded.
+ * If flush() is called on the writer and even if it is less than chunkSize, then the initial response will be sent
+ * with headers, followed by the buffered bytes as the first chunk.
+ * When chunking, an output buffer is allocated only when the previous buffer has been sent
+ * If an error occurs after sending the first chunk, the connection will close abruptly.
+ *
+ * Here is a breakdown of the possible cases.
+ * 1. smaller than chunkSize, no error -> full response
+ * 2. smaller than chunkSize, error -> full response
+ * 3. larger than chunkSize, error after header-> close connection. release buffer and release error
+ * 4. larger than chunkSize, no error. -> header, data, empty response
+ */
 public class ChunkedResponse implements IServletResponse {
     private final ChannelHandlerContext ctx;
     private final ChunkedNettyOutputStream outputStream;
@@ -45,12 +64,13 @@ public class ChunkedResponse implements IServletResponse {
     private boolean headerSent;
     private ByteBuf error;
     private ChannelFuture future;
+    private boolean done;
 
-    public ChunkedResponse(ChannelHandlerContext ctx, FullHttpRequest request) {
+    public ChunkedResponse(ChannelHandlerContext ctx, FullHttpRequest request, int chunkSize) {
         this.ctx = ctx;
-        outputStream = new ChunkedNettyOutputStream(ctx, 4096, this);
+        outputStream = new ChunkedNettyOutputStream(ctx, chunkSize, this);
         writer = new PrintWriter(outputStream);
-        response = new DefaultHttpResponse(HTTP_1_1, OK);
+        response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR);
         response.headers().set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
         if (HttpUtil.isKeepAlive(request)) {
             response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
@@ -67,7 +87,7 @@ public class ChunkedResponse implements IServletResponse {
     }
 
     @Override
-    public ChannelFuture future() {
+    public ChannelFuture lastContentFuture() {
         return future;
     }
 
@@ -78,25 +98,45 @@ public class ChunkedResponse implements IServletResponse {
 
     @Override
     public void close() throws IOException {
-        if (error == null) {
-            writer.close();
-            future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
+        writer.close();
+        if (error == null && response.status() == HttpResponseStatus.OK) {
+            if (!done) {
+                future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
+            }
+        } else {
+            // There was an error
+            if (headerSent) {
+                if (error != null) {
+                    error.release();
+                }
+                future = ctx.channel().close();
+            } else {
+                // we didn't send anything to the user, we need to send an unchunked error response
+                fullResponse(response.protocolVersion(), response.status(),
+                        error == null ? ctx.alloc().buffer(0, 0) : error, response.headers());
+            }
         }
+        done = true;
     }
 
     public HttpResponseStatus status() {
         return response.status();
     }
 
-    public void flush() {
+    public void beforeFlush() {
         if (!headerSent && response.status() == HttpResponseStatus.OK) {
-            ctx.writeAndFlush(response);
+            ctx.write(response, ctx.channel().voidPromise());
             headerSent = true;
         }
     }
 
     public void error(ByteBuf error) {
-        this.error = error;
+        if (this.error == null) {
+            this.error = error;
+        } else {
+            this.error.capacity(this.error.capacity() + error.capacity());
+            this.error.writeBytes(error);
+        }
     }
 
     @Override
@@ -106,8 +146,28 @@ public class ChunkedResponse implements IServletResponse {
 
     @Override
     public void setStatus(HttpResponseStatus status) {
-        // update the response
-        // close the stream
-        // write the response
+        response.setStatus(status);
+    }
+
+    public boolean isHeaderSent() {
+        return headerSent;
+    }
+
+    public void fullReponse(ByteBuf buffer) {
+        fullResponse(response.protocolVersion(), response.status(), buffer, response.headers());
+    }
+
+    private void fullResponse(HttpVersion version, HttpResponseStatus status, ByteBuf buffer, HttpHeaders headers) {
+        DefaultFullHttpResponse fullResponse = new DefaultFullHttpResponse(version, status, buffer);
+        fullResponse.headers().set(headers);
+        fullResponse.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, buffer.readableBytes());
+        future = ctx.writeAndFlush(fullResponse);
+        headerSent = true;
+        done = true;
+    }
+
+    @Override
+    public void notifyChannelWritable() {
+        outputStream.resume();
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FullResponse.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FullResponse.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FullResponse.java
index 245f28a..1023686 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FullResponse.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/FullResponse.java
@@ -23,6 +23,8 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 
+import org.apache.hyracks.http.api.IServletResponse;
+
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
@@ -80,7 +82,7 @@ public class FullResponse implements IServletResponse {
     }
 
     @Override
-    public ChannelFuture future() throws IOException {
+    public ChannelFuture lastContentFuture() throws IOException {
         return future;
     }
 
@@ -93,4 +95,10 @@ public class FullResponse implements IServletResponse {
     public void setStatus(HttpResponseStatus status) {
         response.setStatus(status);
     }
+
+    @Override
+    public void notifyChannelWritable() {
+        // Do nothing.
+        // This response is sent as a single piece
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/GetRequest.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/GetRequest.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/GetRequest.java
index 0b80a78..8d308d3 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/GetRequest.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/GetRequest.java
@@ -21,6 +21,9 @@ package org.apache.hyracks.http.server;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.server.util.ServletUtils;
+
 import io.netty.handler.codec.http.FullHttpRequest;
 
 public class GetRequest implements IServletRequest {
@@ -39,12 +42,11 @@ public class GetRequest implements IServletRequest {
 
     @Override
     public String getParameter(CharSequence name) {
-        return IServletRequest.getParameter(parameters, name);
+        return ServletUtils.getParameter(parameters, name);
     }
 
     @Override
     public String getHeader(CharSequence name) {
         return request.headers().get(name);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/088991c5/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpRequestHandler.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpRequestHandler.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpRequestHandler.java
new file mode 100644
index 0000000..418cd26
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpRequestHandler.java
@@ -0,0 +1,84 @@
+/*
+ * 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.hyracks.http.server;
+
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
+
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpUtil;
+
+public class HttpRequestHandler implements Callable<Void> {
+    private static final Logger LOGGER = Logger.getLogger(HttpRequestHandler.class.getName());
+    private final ChannelHandlerContext ctx;
+    private final IServlet servlet;
+    private final IServletRequest request;
+    private final IServletResponse response;
+
+    public HttpRequestHandler(ChannelHandlerContext ctx, IServlet servlet, IServletRequest request, int chunkSize) {
+        this.ctx = ctx;
+        this.servlet = servlet;
+        this.request = request;
+        response = chunkSize == 0 ? new FullResponse(ctx, request.getHttpRequest())
+                : new ChunkedResponse(ctx, request.getHttpRequest(), chunkSize);
+        request.getHttpRequest().retain();
+    }
+
+    @Override
+    public Void call() throws Exception {
+        try {
+            ChannelFuture lastContentFuture = handle();
+            if (!HttpUtil.isKeepAlive(request.getHttpRequest())) {
+                lastContentFuture.addListener(ChannelFutureListener.CLOSE);
+            }
+        } catch (Throwable th) { //NOSONAR
+            LOGGER.log(Level.SEVERE, "Failure handling HTTP Request", th);
+            ctx.close();
+        } finally {
+            request.getHttpRequest().release();
+        }
+        return null;
+    }
+
+    private ChannelFuture handle() throws IOException {
+        try {
+            servlet.handle(request, response);
+        } catch (Exception e) {
+            LOGGER.log(Level.WARNING, "Failure during handling of an IServletRequest", e);
+            response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
+        } finally {
+            response.close();
+        }
+        return response.lastContentFuture();
+    }
+
+    public void notifyChannelWritable() {
+        response.notifyChannelWritable();
+    }
+
+}


Mime
View raw message