Implement the servlets required for each REST API endpoint.

git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_stabilization_result_distribution@1149 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/DDLAPIServlet.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/DDLAPIServlet.java
new file mode 100644
index 0000000..0d11890
--- /dev/null
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/DDLAPIServlet.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2009-2011 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     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 edu.uci.ics.asterix.api.http.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import edu.uci.ics.asterix.api.common.APIFramework.DisplayFormat;
+import edu.uci.ics.asterix.api.common.SessionConfig;
+import edu.uci.ics.asterix.aql.base.Statement;
+import edu.uci.ics.asterix.aql.parser.AQLParser;
+import edu.uci.ics.asterix.aql.parser.ParseException;
+import edu.uci.ics.asterix.aql.translator.AqlTranslator;
+import edu.uci.ics.asterix.metadata.MetadataManager;
+import edu.uci.ics.asterix.result.ResultReader;
+import edu.uci.ics.hyracks.api.client.HyracksConnection;
+import edu.uci.ics.hyracks.api.client.IHyracksClientConnection;
+
+public class DDLAPIServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+
+    private static final String HYRACKS_CONNECTION_ATTR = "edu.uci.ics.asterix.HYRACKS_CONNECTION";
+
+    @Override
+    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        String query = request.getParameter("query");
+        String strIP = request.getParameter("hyracks-ip");
+        String strPort = request.getParameter("hyracks-port");
+        int port = Integer.parseInt(strPort);
+        PrintWriter out = response.getWriter();
+        response.setContentType("text/html");
+        ServletContext context = getServletContext();
+        IHyracksClientConnection hcc;
+        ResultReader resultReader;
+        try {
+            synchronized (context) {
+                hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
+                if (hcc == null) {
+                    hcc = new HyracksConnection(strIP, port);
+                    context.setAttribute(HYRACKS_CONNECTION_ATTR, hcc);
+                }
+                resultReader = new ResultReader(hcc, out);
+                new Thread(resultReader).start();
+            }
+            AQLParser parser = new AQLParser(new StringReader(query));
+            List<Statement> aqlStatements = parser.Statement();
+            SessionConfig sessionConfig = new SessionConfig(port, true, false, false, false, false, false, false, false);
+
+            MetadataManager.INSTANCE.init();
+
+            AqlTranslator aqlTranslator = new AqlTranslator(aqlStatements, out, sessionConfig, DisplayFormat.HTML);
+
+            aqlTranslator.compileAndExecute(hcc, resultReader);
+
+        } catch (ParseException pe) {
+            String message = pe.getMessage();
+            message = message.replace("<", "&lt");
+            message = message.replace(">", "&gt");
+            out.println("SyntaxError:" + message);
+            int pos = message.indexOf("line");
+            if (pos > 0) {
+                int columnPos = message.indexOf(",", pos + 1 + "line".length());
+                int lineNo = Integer.parseInt(message.substring(pos + "line".length() + 1, columnPos));
+                String line = query.split("\n")[lineNo - 1];
+                out.println("==> " + line);
+            }
+        } catch (Exception e) {
+            out.println(e.getMessage());
+            e.printStackTrace(out);
+        }
+    }
+}
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/QueryAPIServlet.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/QueryAPIServlet.java
new file mode 100644
index 0000000..92bfb3f
--- /dev/null
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/QueryAPIServlet.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2009-2011 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     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 edu.uci.ics.asterix.api.http.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import edu.uci.ics.asterix.api.common.APIFramework.DisplayFormat;
+import edu.uci.ics.asterix.api.common.SessionConfig;
+import edu.uci.ics.asterix.aql.base.Statement;
+import edu.uci.ics.asterix.aql.parser.AQLParser;
+import edu.uci.ics.asterix.aql.parser.ParseException;
+import edu.uci.ics.asterix.aql.translator.AqlTranslator;
+import edu.uci.ics.asterix.metadata.MetadataManager;
+import edu.uci.ics.hyracks.api.client.HyracksConnection;
+import edu.uci.ics.hyracks.api.client.IHyracksClientConnection;
+
+public class QueryAPIServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+
+    private static final String HYRACKS_CONNECTION_ATTR = "edu.uci.ics.asterix.HYRACKS_CONNECTION";
+
+    @Override
+    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        String query = request.getParameter("query");
+        String mode = request.getParameter("mode");
+        boolean asyncResults = false;
+        if (mode != null && mode.equals("asynchronous")) {
+            asyncResults = true;
+        }
+        String strIP = "127.0.0.1";
+        String strPort = "1098";
+        int port = Integer.parseInt(strPort);
+        PrintWriter out = response.getWriter();
+        response.setContentType("text/html");
+        ServletContext context = getServletContext();
+        IHyracksClientConnection hcc;
+        try {
+            synchronized (context) {
+                hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
+                if (hcc == null) {
+                    hcc = new HyracksConnection(strIP, port);
+                    context.setAttribute(HYRACKS_CONNECTION_ATTR, hcc);
+                }
+            }
+            AQLParser parser = new AQLParser(new StringReader(query));
+            List<Statement> aqlStatements = parser.Statement();
+            SessionConfig sessionConfig = new SessionConfig(port, true, false, false, false, false, false, true, false);
+
+            MetadataManager.INSTANCE.init();
+
+            AqlTranslator aqlTranslator = new AqlTranslator(aqlStatements, out, sessionConfig, DisplayFormat.HTML);
+
+            aqlTranslator.compileAndExecute(hcc, asyncResults);
+
+        } catch (ParseException pe) {
+            String message = pe.getMessage();
+            message = message.replace("<", "&lt");
+            message = message.replace(">", "&gt");
+            out.println("SyntaxError:" + message);
+            int pos = message.indexOf("line");
+            if (pos > 0) {
+                int columnPos = message.indexOf(",", pos + 1 + "line".length());
+                int lineNo = Integer.parseInt(message.substring(pos + "line".length() + 1, columnPos));
+                String line = query.split("\n")[lineNo - 1];
+                out.println("==> " + line);
+            }
+        } catch (Exception e) {
+            out.println(e.getMessage());
+            e.printStackTrace(out);
+        }
+    }
+}
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/QueryResultAPIServlet.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/QueryResultAPIServlet.java
new file mode 100644
index 0000000..e1950f9
--- /dev/null
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/QueryResultAPIServlet.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2009-2011 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     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 edu.uci.ics.asterix.api.http.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import edu.uci.ics.asterix.result.ReaderUtils;
+import edu.uci.ics.asterix.result.ResultReader;
+import edu.uci.ics.asterix.runtime.formats.FormatUtils;
+import edu.uci.ics.hyracks.api.client.HyracksConnection;
+import edu.uci.ics.hyracks.api.client.IHyracksClientConnection;
+import edu.uci.ics.hyracks.api.dataset.ResultSetId;
+import edu.uci.ics.hyracks.api.job.JobId;
+
+public class QueryResultAPIServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+
+    private static final String HYRACKS_CONNECTION_ATTR = "edu.uci.ics.asterix.HYRACKS_CONNECTION";
+
+    @Override
+    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        String strHandle = request.getParameter("handle");
+        String strIP = "127.0.0.1";
+        String strPort = "1098";
+        int port = Integer.parseInt(strPort);
+        PrintWriter out = response.getWriter();
+        response.setContentType("text/html");
+        ServletContext context = getServletContext();
+        IHyracksClientConnection hcc;
+        try {
+            synchronized (context) {
+                hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
+                if (hcc == null) {
+                    hcc = new HyracksConnection(strIP, port);
+                    context.setAttribute(HYRACKS_CONNECTION_ATTR, hcc);
+                }
+            }
+            JSONObject handleObj = new JSONObject(strHandle);
+            JSONArray handle = handleObj.getJSONArray("handle");
+            JobId jobId = new JobId(handle.getLong(0));
+            ResultSetId rsId = new ResultSetId(handle.getLong(1));
+            ByteBuffer buffer = ByteBuffer.allocate(ResultReader.FRAME_SIZE);
+            /* TODO(madhusudancs): We need to find a way to JSON serialize default format obtained from
+             * metadataProvider in the AQLTranslator and store it as part of the result handle.
+             */
+            ResultReader resultReader = new ResultReader(hcc, FormatUtils.getDefaultFormat());
+            resultReader.open(jobId, rsId);
+            buffer.clear();
+            JSONObject jsonResponse = new JSONObject();
+            JSONArray results = new JSONArray();
+            while (resultReader.read(buffer) > 0) {
+                results.put(ReaderUtils.getJSONFromBuffer(buffer, resultReader.getFrameTupleAccessor(),
+                        resultReader.getRecordDescriptor()));
+            }
+            jsonResponse.put("results", results);
+            out.write(jsonResponse.toString());
+
+        } catch (Exception e) {
+            out.println(e.getMessage());
+            e.printStackTrace(out);
+        }
+    }
+}
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/QueryStatusAPIServlet.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/QueryStatusAPIServlet.java
new file mode 100644
index 0000000..818790b
--- /dev/null
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/QueryStatusAPIServlet.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2009-2011 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     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 edu.uci.ics.asterix.api.http.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import edu.uci.ics.asterix.api.common.APIFramework.DisplayFormat;
+import edu.uci.ics.asterix.api.common.SessionConfig;
+import edu.uci.ics.asterix.aql.base.Statement;
+import edu.uci.ics.asterix.aql.parser.AQLParser;
+import edu.uci.ics.asterix.aql.parser.ParseException;
+import edu.uci.ics.asterix.aql.translator.AqlTranslator;
+import edu.uci.ics.asterix.metadata.MetadataManager;
+import edu.uci.ics.asterix.result.ResultReader;
+import edu.uci.ics.hyracks.api.client.HyracksConnection;
+import edu.uci.ics.hyracks.api.client.IHyracksClientConnection;
+
+public class QueryStatusAPIServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+
+    private static final String HYRACKS_CONNECTION_ATTR = "edu.uci.ics.asterix.HYRACKS_CONNECTION";
+
+    @Override
+    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        String query = request.getParameter("query");
+        String strIP = request.getParameter("hyracks-ip");
+        String strPort = request.getParameter("hyracks-port");
+        int port = Integer.parseInt(strPort);
+        PrintWriter out = response.getWriter();
+        response.setContentType("text/html");
+        ServletContext context = getServletContext();
+        IHyracksClientConnection hcc;
+        ResultReader resultReader;
+        try {
+            synchronized (context) {
+                hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
+                if (hcc == null) {
+                    hcc = new HyracksConnection(strIP, port);
+                    context.setAttribute(HYRACKS_CONNECTION_ATTR, hcc);
+                }
+                resultReader = new ResultReader(hcc, out);
+                new Thread(resultReader).start();
+            }
+            AQLParser parser = new AQLParser(new StringReader(query));
+            List<Statement> aqlStatements = parser.Statement();
+            SessionConfig sessionConfig = new SessionConfig(port, true, false, false, false, false, false, false, false);
+
+            MetadataManager.INSTANCE.init();
+
+            AqlTranslator aqlTranslator = new AqlTranslator(aqlStatements, out, sessionConfig, DisplayFormat.HTML);
+
+            aqlTranslator.compileAndExecute(hcc, resultReader);
+
+        } catch (ParseException pe) {
+            String message = pe.getMessage();
+            message = message.replace("<", "&lt");
+            message = message.replace(">", "&gt");
+            out.println("SyntaxError:" + message);
+            int pos = message.indexOf("line");
+            if (pos > 0) {
+                int columnPos = message.indexOf(",", pos + 1 + "line".length());
+                int lineNo = Integer.parseInt(message.substring(pos + "line".length() + 1, columnPos));
+                String line = query.split("\n")[lineNo - 1];
+                out.println("==> " + line);
+            }
+        } catch (Exception e) {
+            out.println(e.getMessage());
+            e.printStackTrace(out);
+        }
+    }
+}
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/UpdateAPIServlet.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/UpdateAPIServlet.java
new file mode 100644
index 0000000..a9c1a10
--- /dev/null
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/UpdateAPIServlet.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2009-2011 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     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 edu.uci.ics.asterix.api.http.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import edu.uci.ics.asterix.api.common.APIFramework.DisplayFormat;
+import edu.uci.ics.asterix.api.common.SessionConfig;
+import edu.uci.ics.asterix.aql.base.Statement;
+import edu.uci.ics.asterix.aql.parser.AQLParser;
+import edu.uci.ics.asterix.aql.parser.ParseException;
+import edu.uci.ics.asterix.aql.translator.AqlTranslator;
+import edu.uci.ics.asterix.metadata.MetadataManager;
+import edu.uci.ics.asterix.result.ResultReader;
+import edu.uci.ics.hyracks.api.client.HyracksConnection;
+import edu.uci.ics.hyracks.api.client.IHyracksClientConnection;
+
+public class UpdateAPIServlet extends HttpServlet {
+    private static final long serialVersionUID = 1L;
+
+    private static final String HYRACKS_CONNECTION_ATTR = "edu.uci.ics.asterix.HYRACKS_CONNECTION";
+
+    @Override
+    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        String query = request.getParameter("query");
+        String strIP = request.getParameter("hyracks-ip");
+        String strPort = request.getParameter("hyracks-port");
+        int port = Integer.parseInt(strPort);
+        PrintWriter out = response.getWriter();
+        response.setContentType("text/html");
+        ServletContext context = getServletContext();
+        IHyracksClientConnection hcc;
+        ResultReader resultReader;
+        try {
+            synchronized (context) {
+                hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
+                if (hcc == null) {
+                    hcc = new HyracksConnection(strIP, port);
+                    context.setAttribute(HYRACKS_CONNECTION_ATTR, hcc);
+                }
+                resultReader = new ResultReader(hcc, out);
+                new Thread(resultReader).start();
+            }
+            AQLParser parser = new AQLParser(new StringReader(query));
+            List<Statement> aqlStatements = parser.Statement();
+            SessionConfig sessionConfig = new SessionConfig(port, true, false, false, false, false, false, false, false);
+
+            MetadataManager.INSTANCE.init();
+
+            AqlTranslator aqlTranslator = new AqlTranslator(aqlStatements, out, sessionConfig, DisplayFormat.HTML);
+
+            aqlTranslator.compileAndExecute(hcc, resultReader);
+
+        } catch (ParseException pe) {
+            String message = pe.getMessage();
+            message = message.replace("<", "&lt");
+            message = message.replace(">", "&gt");
+            out.println("SyntaxError:" + message);
+            int pos = message.indexOf("line");
+            if (pos > 0) {
+                int columnPos = message.indexOf(",", pos + 1 + "line".length());
+                int lineNo = Integer.parseInt(message.substring(pos + "line".length() + 1, columnPos));
+                String line = query.split("\n")[lineNo - 1];
+                out.println("==> " + line);
+            }
+        } catch (Exception e) {
+            out.println(e.getMessage());
+            e.printStackTrace(out);
+        }
+    }
+}
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/CCBootstrapImpl.java b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/CCBootstrapImpl.java
index 434f44c..54e26dd 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/CCBootstrapImpl.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/CCBootstrapImpl.java
@@ -30,6 +30,11 @@
 import edu.uci.ics.asterix.api.aqlj.server.ThreadedServer;
 import edu.uci.ics.asterix.api.http.servlet.APIServlet;
 import edu.uci.ics.asterix.common.api.AsterixAppContextInfoImpl;
+import edu.uci.ics.asterix.api.http.servlet.DDLAPIServlet;
+import edu.uci.ics.asterix.api.http.servlet.QueryAPIServlet;
+import edu.uci.ics.asterix.api.http.servlet.QueryResultAPIServlet;
+import edu.uci.ics.asterix.api.http.servlet.QueryStatusAPIServlet;
+import edu.uci.ics.asterix.api.http.servlet.UpdateAPIServlet;
 import edu.uci.ics.asterix.common.config.GlobalConfig;
 import edu.uci.ics.asterix.metadata.MetadataManager;
 import edu.uci.ics.asterix.metadata.api.IAsterixStateProxy;
@@ -47,10 +52,13 @@
 
     private static final int DEFAULT_WEB_SERVER_PORT = 19001;
 
+    private static final int DEFAULT_JSON_API_SERVER_PORT = 19101;
+
     public static final int DEFAULT_API_SERVER_PORT = 14600;
     private static final int DEFAULT_API_NODEDATA_SERVER_PORT = 14601;
 
     private Server webServer;
+    private Server jsonAPIServer;
     private static IAsterixStateProxy proxy;
     private ICCApplicationContext appCtx;
     private ThreadedServer apiServer;
@@ -73,6 +81,10 @@
         setupWebServer();
         webServer.start();
 
+        // Setup and start the web interface
+        setupJSONAPIServer();
+        jsonAPIServer.start();
+
         // Setup and start the API server
         setupAPIServer();
         apiServer.start();
@@ -111,6 +123,24 @@
         context.addServlet(new ServletHolder(new APIServlet()), "/*");
     }
 
+    private void setupJSONAPIServer() throws Exception {
+        String portStr = System.getProperty(GlobalConfig.JSON_API_SERVER_PORT_PROPERTY);
+        int port = DEFAULT_JSON_API_SERVER_PORT;
+        if (portStr != null) {
+            port = Integer.parseInt(portStr);
+        }
+        jsonAPIServer = new Server(port);
+
+        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+        context.setContextPath("/");
+        jsonAPIServer.setHandler(context);
+        context.addServlet(new ServletHolder(new QueryAPIServlet()), "/query");
+        context.addServlet(new ServletHolder(new QueryStatusAPIServlet()), "/query/status");
+        context.addServlet(new ServletHolder(new QueryResultAPIServlet()), "/query/result");
+        context.addServlet(new ServletHolder(new UpdateAPIServlet()), "/update");
+        context.addServlet(new ServletHolder(new DDLAPIServlet()), "/ddl");
+    }
+
     private void setupAPIServer() throws Exception {
         // set the APINodeDataServer ports
         int startPort = DEFAULT_API_NODEDATA_SERVER_PORT;
diff --git a/asterix-common/src/main/java/edu/uci/ics/asterix/common/config/GlobalConfig.java b/asterix-common/src/main/java/edu/uci/ics/asterix/common/config/GlobalConfig.java
index bb39f90..137bfec 100644
--- a/asterix-common/src/main/java/edu/uci/ics/asterix/common/config/GlobalConfig.java
+++ b/asterix-common/src/main/java/edu/uci/ics/asterix/common/config/GlobalConfig.java
@@ -19,6 +19,8 @@
 
     public static final String WEB_SERVER_PORT_PROPERTY = "AsterixWebServerPort";
 
+    public static final String JSON_API_SERVER_PORT_PROPERTY = "AsterixJSONAPIServerPort";
+
     public static final String BUFFER_CACHE_PAGE_SIZE_PROPERTY = "BufferCachePageSize";
 
     public static final String BUFFER_CACHE_NUM_PAGES_PROPERTY = "BufferCacheNumPages";