Extension Points For Servlets

Change-Id: Iff794b1c21296c50867b7430a0652924b5cf31d2
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1019
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <tillw@apache.org>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/APIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/APIServlet.java
index 7a47ca9..204ff5c 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/APIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/APIServlet.java
@@ -55,14 +55,14 @@
 import org.apache.hyracks.api.dataset.IHyracksDataset;
 import org.apache.hyracks.client.dataset.HyracksDataset;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
+
 public class APIServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
 
     private static final Logger LOGGER = Logger.getLogger(APIServlet.class.getName());
 
-    private static final String HYRACKS_CONNECTION_ATTR = "org.apache.asterix.HYRACKS_CONNECTION";
-    private static final String HYRACKS_DATASET_ATTR = "org.apache.asterix.HYRACKS_DATASET";
-
     private final ILangCompilationProvider aqlCompilationProvider;
     private final ILangCompilationProvider sqlppCompilationProvider;
 
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ConnectorAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ConnectorAPIServlet.java
index c70950a..bca6d35 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ConnectorAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ConnectorAPIServlet.java
@@ -43,6 +43,8 @@
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+
 /***
  * The REST API that takes a dataverse name and a dataset name as the input
  * and returns an array of file splits (IP, file-path) of the dataset in LOSSLESS_JSON.
@@ -54,8 +56,6 @@
 public class ConnectorAPIServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
 
-    private static final String HYRACKS_CONNECTION_ATTR = "org.apache.asterix.HYRACKS_CONNECTION";
-
     @Override
     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
         response.setContentType("text/html");
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java
index 0f9c537..943691d 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.api.http.servlet;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
@@ -28,13 +29,15 @@
 
 public class DDLAPIServlet extends RESTAPIServlet {
     private static final long serialVersionUID = 1L;
-    private static final List<Byte> STATEMENTS = Arrays.asList(new Byte[] { Statement.Kind.DATAVERSE_DECL,
-            Statement.Kind.DATAVERSE_DROP, Statement.Kind.DATASET_DECL, Statement.Kind.NODEGROUP_DECL,
-            Statement.Kind.NODEGROUP_DROP, Statement.Kind.TYPE_DECL, Statement.Kind.TYPE_DROP,
-            Statement.Kind.CREATE_INDEX, Statement.Kind.INDEX_DECL, Statement.Kind.CREATE_DATAVERSE,
-            Statement.Kind.DATASET_DROP, Statement.Kind.INDEX_DROP, Statement.Kind.CREATE_FUNCTION,
-            Statement.Kind.FUNCTION_DROP, Statement.Kind.CREATE_PRIMARY_FEED, Statement.Kind.CREATE_SECONDARY_FEED,
-            Statement.Kind.DROP_FEED, Statement.Kind.CREATE_FEED_POLICY, Statement.Kind.DROP_FEED_POLICY });
+
+    private static final List<Byte> allowedStatements = Collections.unmodifiableList(Arrays.asList(
+            Statement.Kind.DATAVERSE_DECL, Statement.Kind.DATAVERSE_DROP, Statement.Kind.DATASET_DECL,
+            Statement.Kind.NODEGROUP_DECL, Statement.Kind.NODEGROUP_DROP, Statement.Kind.TYPE_DECL,
+            Statement.Kind.TYPE_DROP, Statement.Kind.CREATE_INDEX, Statement.Kind.INDEX_DECL,
+            Statement.Kind.CREATE_DATAVERSE, Statement.Kind.DATASET_DROP, Statement.Kind.INDEX_DROP,
+            Statement.Kind.CREATE_FUNCTION, Statement.Kind.FUNCTION_DROP, Statement.Kind.CREATE_PRIMARY_FEED,
+            Statement.Kind.CREATE_SECONDARY_FEED, Statement.Kind.DROP_FEED, Statement.Kind.CREATE_FEED_POLICY,
+            Statement.Kind.DROP_FEED_POLICY));
 
     public DDLAPIServlet(ILangCompilationProvider compilationProvider) {
         super(compilationProvider);
@@ -47,7 +50,7 @@
 
     @Override
     protected List<Byte> getAllowedStatements() {
-        return STATEMENTS;
+        return allowedStatements;
     }
 
     @Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java
index 7262b59..63aa2df 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.api.http.servlet;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
@@ -28,9 +29,10 @@
 
 public class QueryAPIServlet extends RESTAPIServlet {
     private static final long serialVersionUID = 1L;
-    private static final List<Byte> STATEMENTS =
-            Arrays.asList(new Byte[] { Statement.Kind.DATAVERSE_DECL, Statement.Kind.FUNCTION_DECL,
-                    Statement.Kind.QUERY, Statement.Kind.SET, Statement.Kind.WRITE, Statement.Kind.RUN });
+
+    private static final List<Byte> allowedStatements = Collections.unmodifiableList(Arrays.asList(
+            Statement.Kind.DATAVERSE_DECL, Statement.Kind.FUNCTION_DECL, Statement.Kind.QUERY, Statement.Kind.SET,
+            Statement.Kind.WRITE, Statement.Kind.RUN));
 
     public QueryAPIServlet(ILangCompilationProvider compilationProvider) {
         super(compilationProvider);
@@ -43,7 +45,7 @@
 
     @Override
     protected List<Byte> getAllowedStatements() {
-        return STATEMENTS;
+        return allowedStatements;
     }
 
     @Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryResultAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryResultAPIServlet.java
index 3198759..9d29adf 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryResultAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryResultAPIServlet.java
@@ -38,13 +38,12 @@
 import org.json.JSONArray;
 import org.json.JSONObject;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
+
 public class QueryResultAPIServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
 
-    private static final String HYRACKS_CONNECTION_ATTR = "org.apache.asterix.HYRACKS_CONNECTION";
-
-    private static final String HYRACKS_DATASET_ATTR = "org.apache.asterix.HYRACKS_DATASET";
-
     @Override
     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
         response.setContentType("text/html");
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
index 5a857d1..2e6ee58 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
@@ -53,14 +53,14 @@
 import org.apache.hyracks.api.dataset.IHyracksDataset;
 import org.apache.hyracks.client.dataset.HyracksDataset;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
+
 public class QueryServiceServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
 
     private static final Logger LOGGER = Logger.getLogger(QueryServiceServlet.class.getName());
 
-    private static final String HYRACKS_CONNECTION_ATTR = "org.apache.asterix.HYRACKS_CONNECTION";
-    private static final String HYRACKS_DATASET_ATTR = "org.apache.asterix.HYRACKS_DATASET";
-
     private transient final ILangCompilationProvider compilationProvider = new SqlppCompilationProvider();
 
     public enum Parameter {
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryStatusAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryStatusAPIServlet.java
index 2751945..2eb5e81 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryStatusAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryStatusAPIServlet.java
@@ -36,13 +36,12 @@
 import org.apache.hyracks.api.job.JobId;
 import org.apache.hyracks.client.dataset.HyracksDataset;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
+
 public class QueryStatusAPIServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
 
-    private static final String HYRACKS_CONNECTION_ATTR = "org.apache.asterix.HYRACKS_CONNECTION";
-
-    private static final String HYRACKS_DATASET_ATTR = "org.apache.asterix.HYRACKS_DATASET";
-
     @Override
     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
         response.setContentType("text/html");
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/RESTAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/RESTAPIServlet.java
index 7ca1442..1045124 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/RESTAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/RESTAPIServlet.java
@@ -49,13 +49,12 @@
 import org.apache.hyracks.client.dataset.HyracksDataset;
 import org.json.JSONObject;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
+
 abstract class RESTAPIServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
 
-    public static final String HYRACKS_CONNECTION_ATTR = "org.apache.asterix.HYRACKS_CONNECTION";
-
-    public static final String HYRACKS_DATASET_ATTR = "org.apache.asterix.HYRACKS_DATASET";
-
     private final ILangCompilationProvider compilationProvider;
     private final IParserFactory parserFactory;
 
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ServletConstants.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ServletConstants.java
new file mode 100644
index 0000000..9e28b02
--- /dev/null
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ServletConstants.java
@@ -0,0 +1,28 @@
+/*
+ * 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.asterix.api.http.servlet;
+
+public class ServletConstants {
+    public static final String HYRACKS_CONNECTION_ATTR = "org.apache.asterix.HYRACKS_CONNECTION";
+    public static final String HYRACKS_DATASET_ATTR = "org.apache.asterix.HYRACKS_DATASET";
+    public static final String ASTERIX_BUILD_PROP_ATTR = "org.apache.asterix.PROPS";
+
+    private ServletConstants() {
+    }
+}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ShutdownAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ShutdownAPIServlet.java
index 7585fd3..e2e7c90 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ShutdownAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ShutdownAPIServlet.java
@@ -35,11 +35,11 @@
 import org.apache.commons.io.IOUtils;
 import org.apache.hyracks.api.client.IHyracksClientConnection;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+
 public class ShutdownAPIServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
 
-    private static final String HYRACKS_CONNECTION_ATTR = "org.apache.asterix.HYRACKS_CONNECTION";
-
     @Override
     protected void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/UpdateAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/UpdateAPIServlet.java
index 22cd963..afa202b 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/UpdateAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/UpdateAPIServlet.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.api.http.servlet;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
@@ -28,11 +29,11 @@
 
 public class UpdateAPIServlet extends RESTAPIServlet {
     private static final long serialVersionUID = 1L;
-    private static final List<Byte> STATEMENTS =
-            Arrays.asList(new Byte[] { Statement.Kind.DATAVERSE_DECL, Statement.Kind.DELETE, Statement.Kind.INSERT,
-                    Statement.Kind.UPSERT, Statement.Kind.UPDATE, Statement.Kind.DML_CMD_LIST, Statement.Kind.LOAD,
-                    Statement.Kind.CONNECT_FEED, Statement.Kind.DISCONNECT_FEED, Statement.Kind.SET,
-                    Statement.Kind.COMPACT, Statement.Kind.EXTERNAL_DATASET_REFRESH, Statement.Kind.RUN });
+    private static final List<Byte> allowedStatements = Collections.unmodifiableList(Arrays.asList(
+            Statement.Kind.DATAVERSE_DECL, Statement.Kind.DELETE, Statement.Kind.INSERT,
+            Statement.Kind.UPSERT, Statement.Kind.UPDATE, Statement.Kind.DML_CMD_LIST, Statement.Kind.LOAD,
+            Statement.Kind.CONNECT_FEED, Statement.Kind.DISCONNECT_FEED, Statement.Kind.SET,
+            Statement.Kind.COMPACT, Statement.Kind.EXTERNAL_DATASET_REFRESH, Statement.Kind.RUN));
 
     public UpdateAPIServlet(ILangCompilationProvider compilationProvider) {
         super(compilationProvider);
@@ -45,7 +46,7 @@
 
     @Override
     protected List<Byte> getAllowedStatements() {
-        return STATEMENTS;
+        return allowedStatements;
     }
 
     @Override
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/VersionAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/VersionAPIServlet.java
index 424421a..a426d50 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/VersionAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/VersionAPIServlet.java
@@ -30,9 +30,10 @@
 import org.apache.asterix.om.util.AsterixAppContextInfo;
 import org.json.JSONObject;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.ASTERIX_BUILD_PROP_ATTR;
+
 public class VersionAPIServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
-    public static final String ASTERIX_BUILD_PROP_ATTR = "org.apache.asterix.PROPS";
 
     @Override
     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
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 324194d..b77544e 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
@@ -18,9 +18,13 @@
  */
 package org.apache.asterix.hyracks.bootstrap;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.servlet.Servlet;
+
 import org.apache.asterix.api.http.servlet.APIServlet;
 import org.apache.asterix.api.http.servlet.AQLAPIServlet;
 import org.apache.asterix.api.http.servlet.ClusterAPIServlet;
@@ -64,23 +68,21 @@
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.ASTERIX_BUILD_PROP_ATTR;
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+
 public class CCApplicationEntryPoint implements ICCApplicationEntryPoint {
 
     private static final Logger LOGGER = Logger.getLogger(CCApplicationEntryPoint.class.getName());
-    private static final String HYRACKS_CONNECTION_ATTR = "org.apache.asterix.HYRACKS_CONNECTION";
-    private static final String ASTERIX_BUILD_PROP_ATTR = "org.apache.asterix.PROPS";
 
-    private Server webServer;
-    private Server jsonAPIServer;
-    private Server feedServer;
+    private List<Server> servers;
 
     private static IAsterixStateProxy proxy;
-    private ICCApplicationContext appCtx;
-    private IMessageBroker messageBroker;
+    protected ICCApplicationContext appCtx;
 
     @Override
     public void start(ICCApplicationContext ccAppCtx, String[] args) throws Exception {
-        messageBroker = new CCMessageBroker((ClusterControllerService) ccAppCtx.getControllerService());
+        IMessageBroker messageBroker = new CCMessageBroker((ClusterControllerService) ccAppCtx.getControllerService());
         this.appCtx = ccAppCtx;
 
         if (LOGGER.isLoggable(Level.INFO)) {
@@ -103,14 +105,11 @@
         AsterixAppContextInfo.getInstance().getCCApplicationContext()
                 .addJobLifecycleListener(ActiveLifecycleListener.INSTANCE);
 
-        AsterixExternalProperties externalProperties = AsterixAppContextInfo.getInstance().getExternalProperties();
-        setupWebServer(externalProperties);
-        webServer.start();
-        setupJSONAPIServer(externalProperties);
-        jsonAPIServer.start();
+        servers = configureServers();
 
-        setupFeedServer(externalProperties);
-        feedServer.start();
+        for (Server server : servers) {
+            server.start();
+        }
 
         ClusterManager.INSTANCE.registerSubscriber(GlobalRecoveryManager.INSTANCE);
 
@@ -118,6 +117,16 @@
         ccAppCtx.setMessageBroker(messageBroker);
     }
 
+    protected List<Server> configureServers() throws Exception {
+        AsterixExternalProperties externalProperties = AsterixAppContextInfo.getInstance().getExternalProperties();
+
+        List<Server> serverList = new ArrayList<>();
+        serverList.add(setupWebServer(externalProperties));
+        serverList.add(setupJSONAPIServer(externalProperties));
+        serverList.add(setupFeedServer(externalProperties));
+        return serverList;
+    }
+
     @Override
     public void stop() throws Exception {
         ActiveLifecycleListener.INSTANCE.stop();
@@ -126,24 +135,24 @@
         }
         AsterixStateProxy.unregisterRemoteObject();
         // Stop servers
-        webServer.stop();
-        jsonAPIServer.stop();
-        feedServer.stop();
+        for (Server server : servers) {
+            server.stop();
+        }
         // Make sure servers are stopped before proceeding
-        webServer.join();
-        jsonAPIServer.join();
-        feedServer.join();
+        for (Server server : servers) {
+            server.join();
+        }
     }
 
-    private IHyracksClientConnection getNewHyracksClientConnection() throws Exception {
+    protected IHyracksClientConnection getNewHyracksClientConnection() throws Exception {
         String strIP = appCtx.getCCContext().getClusterControllerInfo().getClientNetAddress();
         int port = appCtx.getCCContext().getClusterControllerInfo().getClientNetPort();
         return new HyracksConnection(strIP, port);
     }
 
-    private void setupWebServer(AsterixExternalProperties externalProperties) throws Exception {
+    protected Server setupWebServer(AsterixExternalProperties externalProperties) throws Exception {
 
-        webServer = new Server(externalProperties.getWebInterfacePort());
+        Server webServer = new Server(externalProperties.getWebInterfacePort());
 
         ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
         context.setContextPath("/");
@@ -153,10 +162,12 @@
 
         webServer.setHandler(context);
         context.addServlet(new ServletHolder(new APIServlet()), "/*");
+
+        return webServer;
     }
 
-    private void setupJSONAPIServer(AsterixExternalProperties externalProperties) throws Exception {
-        jsonAPIServer = new Server(externalProperties.getAPIServerPort());
+    protected Server setupJSONAPIServer(AsterixExternalProperties externalProperties) throws Exception {
+        Server jsonAPIServer = new Server(externalProperties.getAPIServerPort());
 
         ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
         context.setContextPath("/");
@@ -168,36 +179,76 @@
         jsonAPIServer.setHandler(context);
 
         // AQL rest APIs.
-        context.addServlet(new ServletHolder(new QueryAPIServlet(new AqlCompilationProvider())),
-                Servlets.AQL_QUERY.getPath());
-        context.addServlet(new ServletHolder(new UpdateAPIServlet(new AqlCompilationProvider())),
-                Servlets.AQL_UPDATE.getPath());
-        context.addServlet(new ServletHolder(new DDLAPIServlet(new AqlCompilationProvider())),
-                Servlets.AQL_DDL.getPath());
-        context.addServlet(new ServletHolder(new AQLAPIServlet(new AqlCompilationProvider())), Servlets.AQL.getPath());
+        addServlet(context, Servlets.AQL_QUERY);
+        addServlet(context, Servlets.AQL_UPDATE);
+        addServlet(context, Servlets.AQL_DDL);
+        addServlet(context, Servlets.AQL);
 
         // SQL++ rest APIs.
-        context.addServlet(new ServletHolder(new QueryAPIServlet(new SqlppCompilationProvider())),
-                Servlets.SQLPP_QUERY.getPath());
-        context.addServlet(new ServletHolder(new UpdateAPIServlet(new SqlppCompilationProvider())),
-                Servlets.SQLPP_UPDATE.getPath());
-        context.addServlet(new ServletHolder(new DDLAPIServlet(new SqlppCompilationProvider())),
-                Servlets.SQLPP_DDL.getPath());
-        context.addServlet(new ServletHolder(new AQLAPIServlet(new SqlppCompilationProvider())),
-                Servlets.SQLPP.getPath());
+        addServlet(context, Servlets.SQLPP_QUERY);
+        addServlet(context, Servlets.SQLPP_UPDATE);
+        addServlet(context, Servlets.SQLPP_DDL);
+        addServlet(context, Servlets.SQLPP);
 
         // Other APIs.
-        context.addServlet(new ServletHolder(new QueryStatusAPIServlet()), Servlets.QUERY_STATUS.getPath());
-        context.addServlet(new ServletHolder(new QueryResultAPIServlet()), Servlets.QUERY_RESULT.getPath());
-        context.addServlet(new ServletHolder(new QueryServiceServlet()), Servlets.QUERY_SERVICE.getPath());
-        context.addServlet(new ServletHolder(new ConnectorAPIServlet()), Servlets.CONNECTOR.getPath());
-        context.addServlet(new ServletHolder(new ShutdownAPIServlet()), Servlets.SHUTDOWN.getPath());
-        context.addServlet(new ServletHolder(new VersionAPIServlet()), Servlets.VERSION.getPath());
-        context.addServlet(new ServletHolder(new ClusterAPIServlet()), Servlets.CLUSTER_STATE.getPath());
+        addServlet(context, Servlets.QUERY_STATUS);
+        addServlet(context, Servlets.QUERY_RESULT);
+        addServlet(context, Servlets.QUERY_SERVICE);
+        addServlet(context, Servlets.CONNECTOR);
+        addServlet(context, Servlets.SHUTDOWN);
+        addServlet(context, Servlets.VERSION);
+        addServlet(context, Servlets.CLUSTER_STATE);
+
+        return jsonAPIServer;
     }
 
-    private void setupFeedServer(AsterixExternalProperties externalProperties) throws Exception {
-        feedServer = new Server(externalProperties.getFeedServerPort());
+    protected void addServlet(ServletContextHandler context, Servlet servlet, String path) {
+        context.addServlet(new ServletHolder(servlet), path);
+    }
+
+    protected void addServlet(ServletContextHandler context, Servlets key) {
+        addServlet(context, createServlet(key), key.getPath());
+    }
+
+    private Servlet createServlet(Servlets key) {
+        switch (key) {
+            case AQL:
+                return new AQLAPIServlet(new AqlCompilationProvider());
+            case AQL_QUERY:
+                return new QueryAPIServlet(new AqlCompilationProvider());
+            case AQL_UPDATE:
+                return new UpdateAPIServlet(new AqlCompilationProvider());
+            case AQL_DDL:
+                return new DDLAPIServlet(new AqlCompilationProvider());
+            case SQLPP:
+                return new AQLAPIServlet(new SqlppCompilationProvider());
+            case SQLPP_QUERY:
+                return new QueryAPIServlet(new SqlppCompilationProvider());
+            case SQLPP_UPDATE:
+                return new UpdateAPIServlet(new SqlppCompilationProvider());
+            case SQLPP_DDL:
+                return new DDLAPIServlet(new SqlppCompilationProvider());
+            case QUERY_STATUS:
+                return new QueryStatusAPIServlet();
+            case QUERY_RESULT:
+                return new QueryResultAPIServlet();
+            case QUERY_SERVICE:
+                return new QueryServiceServlet();
+            case CONNECTOR:
+                return new ConnectorAPIServlet();
+            case SHUTDOWN:
+                return new ShutdownAPIServlet();
+            case VERSION:
+                return new VersionAPIServlet();
+            case CLUSTER_STATE:
+                return new ClusterAPIServlet();
+            default:
+                throw new IllegalStateException(String.valueOf(key));
+        }
+    }
+
+    protected Server setupFeedServer(AsterixExternalProperties externalProperties) throws Exception {
+        Server feedServer = new Server(externalProperties.getFeedServerPort());
 
         ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
         context.setContextPath("/");
@@ -208,6 +259,7 @@
         feedServer.setHandler(context);
         context.addServlet(new ServletHolder(new FeedServlet()), "/");
 
+        return feedServer;
     }
 
     @Override
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/VersionAPIServletTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/VersionAPIServletTest.java
index 120fdfd..015088a 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/VersionAPIServletTest.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/VersionAPIServletTest.java
@@ -19,10 +19,6 @@
 
 package org.apache.asterix.api.http.servlet;
 
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStreamReader;
@@ -44,6 +40,12 @@
 import org.junit.Assert;
 import org.junit.Test;
 
+import static org.apache.asterix.api.http.servlet.ServletConstants.ASTERIX_BUILD_PROP_ATTR;
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
 public class VersionAPIServletTest {
 
     @Test
@@ -70,8 +72,8 @@
         // Sets up mock returns.
         when(servlet.getServletContext()).thenReturn(mockContext);
         when(mockResponse.getWriter()).thenReturn(outputWriter);
-        when(mockContext.getAttribute(RESTAPIServlet.HYRACKS_CONNECTION_ATTR)).thenReturn(mockHcc);
-        when(mockContext.getAttribute(VersionAPIServlet.ASTERIX_BUILD_PROP_ATTR)).thenReturn(mockCtx);
+        when(mockContext.getAttribute(HYRACKS_CONNECTION_ATTR)).thenReturn(mockHcc);
+        when(mockContext.getAttribute(ASTERIX_BUILD_PROP_ATTR)).thenReturn(mockCtx);
         when(mockCtx.getBuildProperties()).thenReturn(mockProperties);
         when(mockProperties.getAllProps()).thenReturn(propMap);
 
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/ServletUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/ServletUtil.java
index b75d16c..9e9bbc5 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/ServletUtil.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/ServletUtil.java
@@ -39,13 +39,14 @@
 
         private final String path;
 
-        private Servlets(String path) {
+        Servlets(String path) {
             this.path = path;
         }
 
         public String getPath() {
             return path;
         }
+
     }
 
     private ServletUtil() {