You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vxquery.apache.org by pr...@apache.org on 2017/08/25 16:59:10 UTC

[2/4] vxquery git commit: [VXQUERY-180] REST Server implementation

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-rest/src/site/markdown/index.md
----------------------------------------------------------------------
diff --git a/vxquery-rest/src/site/markdown/index.md b/vxquery-rest/src/site/markdown/index.md
new file mode 100644
index 0000000..703df65
--- /dev/null
+++ b/vxquery-rest/src/site/markdown/index.md
@@ -0,0 +1,249 @@
+<!--
+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.
+-->
+# VXQuery REST Server
+
+VXQuery REST Server allows users to submit queries and receive results either synchronously or
+asynchronously through the exposed REST API. Along with the statement to be executed, few other parameters can be given as
+well. Complete REST API specification can be found at [REST API Specification](specification.html).
+
+## Installation
+
+No additional steps needed to be taken to get the REST Server up and running. That is, setting up a VXQuery cluster will
+automatically start the REST Server on port `8080`. Please see [VXQuery Cluster Setup](../user_cluster_installation.html)
+to understand how a VXQuery cluster is setup.
+
+## Getting Started
+
+Suppose we want to execute a very simple XQuery like:
+
+```
+for $x in (1, 2.0, 3) return $x
+```
+
+### Async (Default Mode) Example
+
+If we want to send this, following will be the plain HTTP request.
+
+```
+GET http://127.0.1.1:39003/vxquery/query?statement=for+%24x+in+%281%2C+2.0%2C+3%29+return+%24x HTTP/1.1
+```
+
+Note the query parameter `statement=for+%24x+in+%281%2C+2.0%2C+3%29+return+%24x` in which the above mentioned statement
+has been encoded. If we send this request using **cURL**, it will look like follows.
+
+#### Accept: application/json
+
+```
+curl -i -H "Accept: application/json" -X GET "http://localhost:39003/vxquery/query?statement=for+%24x+in+%281%2C+2.0%2C+3%29+return+%24x"
+```
+
+and the response is,
+
+```
+HTTP/1.1 200 OK
+transfer-encoding: chunked
+connection: keep-alive
+Access-Control-Allow-Origin: *
+Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
+content-type: application/json
+content-length: 320
+
+{
+  "status": "success",
+  "requestId": "b0cbe06f-3454-4422-ba23-59150e1c1400",
+  "statement": "for $x in (1, 2.0, 3) return $x",
+  "abstractSyntaxTree": null,
+  "translatedExpressionTree": null,
+  "optimizedExpressionTree": null,
+  "runtimePlan": null,
+  "metrics": {
+    "compileTime": 0,
+    "elapsedTime": 0
+  },
+  "resultId": 6,
+  "resultUrl": "/vxquery/query/result/6"
+}
+```
+
+#### Accept: application/xml
+
+```
+curl -i -H "Accept: application/xml" -X GET "http://localhost:39003/vxquery/query?statement=for+%24x+in+%281%2C+2.0%2C+3%29+return+%24x"
+```
+
+and the response is,
+
+```
+HTTP/1.1 200 OK
+transfer-encoding: chunked
+connection: keep-alive
+Access-Control-Allow-Origin: *
+Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
+content-type: application/xml
+content-length: 403
+
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<asyncQueryResponse>
+    <requestId>d0c2c0ef-2e46-4153-9d4b-1ef4593184e7</requestId>
+    <metrics>
+        <compileTime>0</compileTime>
+        <elapsedTime>0</elapsedTime>
+    </metrics>
+    <statement>for $x in (1, 2.0, 3) return $x</statement>
+    <resultId>8</resultId>
+    <resultUrl>/vxquery/query/result/8</resultUrl>
+</asyncQueryResponse>
+```
+
+#### Result Fetching
+
+Since we have used the default mode (**async**), we only got the **resultId**. Now we have to send another request asking
+for the actual results. Send a cURL request to `/vxquery/query/result/8` to fetch results for result ID 8.
+
+##### Accept: application/json
+
+```
+curl -i -H "Accept: application/json" -X GET "http://localhost:39003/vxquery/query/result/8"
+```
+
+and the response is,
+
+```
+HTTP/1.1 200 OK
+transfer-encoding: chunked
+connection: keep-alive
+Access-Control-Allow-Origin: *
+Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
+content-type: application/json
+content-length: 137
+
+{
+  "status": "success",
+  "requestId": "d0c2c0ef-2e46-4153-9d4b-1ef4593184e7",
+  "results": "1\n2\n3\n",
+  "metrics": {
+    "compileTime": 0,
+    "elapsedTime": 0
+  }
+}
+```
+
+Note the *results* in the JSON content in the response.
+
+##### Accept: application/xml
+
+```
+curl -i -H "Accept: application/xml" -X GET "http://localhost:39003/vxquery/query/result/8"
+```
+
+and the response is,
+
+```
+HTTP/1.1 200 OK
+transfer-encoding: chunked
+connection: keep-alive
+Access-Control-Allow-Origin: *
+Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
+content-type: application/xml
+content-length: 298
+
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<queryResultResponse>
+    <requestId>d0c2c0ef-2e46-4153-9d4b-1ef4593184e7</requestId>
+    <metrics>
+        <compileTime>0</compileTime>
+        <elapsedTime>0</elapsedTime>
+    </metrics>
+    <results>1
+2
+3
+</results>
+</queryResultResponse>
+```
+
+Note the *<results></results>* in the XML content in the response.
+
+### Sync (Synchronous Mode) Example
+
+Similarly to what we did under async requests, we can send the query requests here as well, but with the added query parameter
+`mode=sync` which is to indicate that the response should be a synchronous one. That is, we wait for the query to be 
+executed and the response to arrive.
+
+```
+curl -i -H "Accept: application/xml" -X GET \
+"http://localhost:39003/vxquery/query?statement=for+%24x+in+%281%2C+2.0%2C+3%29+return+%24x&mode=sync"
+```
+
+and the response now contains **results** instead of the **resultId** we received previously.
+
+```
+HTTP/1.1 200 OK
+transfer-encoding: chunked
+connection: keep-alive
+Access-Control-Allow-Origin: *
+Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
+content-type: application/xml
+content-length: 353
+
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<syncQueryResponse>
+    <requestId>93b67f50-4f14-4304-a9b2-f75b4a736df3</requestId>
+    <metrics>
+        <compileTime>0</compileTime>
+        <elapsedTime>0</elapsedTime>
+    </metrics>
+    <statement>for $x in (1, 2.0, 3) return $x</statement>
+    <results>1
+2
+3
+</results>
+</syncQueryResponse>
+```
+
+Similarly with `accept:application/json`,
+
+```
+curl -i -H "Accept: application/json" -X GET \
+"http://localhost:39003/vxquery/query?statement=for+%24x+in+%281%2C+2.0%2C+3%29+return+%24x&mode=sync"
+```
+
+and the response is,
+
+```
+HTTP/1.1 200 OK
+transfer-encoding: chunked
+connection: keep-alive
+Access-Control-Allow-Origin: *
+Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
+content-type: application/json
+content-length: 291
+
+{
+  "status": "success",
+  "requestId": "8010a699-a6f2-423c-91e1-8ac17cd5c5cd",
+  "statement": "for $x in (1, 2.0, 3) return $x",
+  "abstractSyntaxTree": null,
+  "translatedExpressionTree": null,
+  "optimizedExpressionTree": null,
+  "runtimePlan": null,
+  "metrics": {
+    "compileTime": 0,
+    "elapsedTime": 0
+  },
+  "results": "1\n2\n3\n"
+}
+```

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-rest/src/site/markdown/specification.md
----------------------------------------------------------------------
diff --git a/vxquery-rest/src/site/markdown/specification.md b/vxquery-rest/src/site/markdown/specification.md
new file mode 100644
index 0000000..3977439
--- /dev/null
+++ b/vxquery-rest/src/site/markdown/specification.md
@@ -0,0 +1,102 @@
+<!--
+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.
+-->
+# REST API Specification
+
+Swagger configuration of the REST API can be found 
+[here](https://cwiki.apache.org/confluence/display/VXQUERY/SwaggerIO+Configuration). 
+
+**NOTE:** This REST API supports both **content types**, `application/json` and `application/xml`. Based on the `accept` header 
+of your query request, REST API will return the results wither in *json* form or *XML* form. Returned content type 
+defaults to `application/json` if no `accept` header is present.
+
+Base Path **${host}/vxquery**
+
+## Query Request
+
+Request of this type should be submitted for a given *query* to be executed. Depending on the value of the parameter
+`mode`, a **synchronous** response or an **asynchronous** response will be returned
+
+`*` required
+
+| Path | Method |Parameters | Type | Description |
+| ------ | ------ | ------ | ----- |----- |
+| /query | GET  |statement*     | string    | Statement to be executed |
+|       |       |mode           | string    | `sync` or `async`. **async** will return an asynchronous response **(default: async)** |
+|       |       |compileOnly    | boolean   | If `true`, statement will be compiled, but won't be executed (default: false) |
+|       |       |optimization   | integer   | Optimization level (0 - 2,147,483,647). (Default: Full optimization) |
+|       |       |frameSize      | integer   | Frame size in bytes (default: 65536) |
+|       |       |repeatExecutions|integer   | Number of times to repeat execution (default: 1) |
+|       |       |metrics        | boolean   | If `true`, returns metrics (compile and execution time) with the response (default: false) |
+|       |       |showAbstractSyntaxTree         | boolean | Shows abstract syntax tree if `true` (default: false) |
+|       |       |showTranslatedExpressionTree   | boolean | Shows translated expression tree if `true` (default: false) |
+|       |       |showOptimizedExpressionTree    | boolean | Shows optimized expression tree if `true` (default: false) |
+|       |       |showRuntimePlan| boolean   | Shows runtime plan if set to `true` (default: false) |
+
+### Synchronous Query Response
+
+Received only when `mode` is set to `sync` in the query request above. 
+
+| Attribute | Type | Description |
+| ------ | ------ | ------ |
+|statement* |string         | Statement submitted to be executed |
+|status*	|string         | `success` to indicate that the query execution was successful | 
+|requestId*	|string         | A unique ID assigned to the request sent earlier |
+|abstractSyntaxTree	        |string | Abstract Syntax Tree if requested in the query request. Else `null` |
+|translatedExpressionTree    |string | Translated Expression Tree if requested in the query request. Else `null` |
+|optimizedExpressionTree	    |string | Optimized Expression Tree if requested in the query request. Else `null` |
+|runtimePlan    |string     | Runtime plan if requested in the query request. Else `null` |
+|metrics	    |metrics    | Metrics (`compileTime` and `elapsedTime`) if requested in the query request |
+|results*       |string     | Results of the query/statement submitted for execution |
+
+### Asynchronous Query Response
+
+Received only when `mode` is set to `async` (which is the default value) in the query request above. 
+
+| Attribute | Type | Description |
+| ------ | ------ | ------ |
+|statement* |string         | Statement submitted to be executed |
+|status*	|string         | `success` to indicate that the query execution was successful | 
+|requestId*	|string         | A unique ID assigned to the request sent earlier |
+|abstractSyntaxTree	        |string | Abstract Syntax Tree if requested in the query request. Else `null` |
+|translatedExpressionTree    |string | Translated Expression Tree if requested in the query request. Else `null` |
+|optimizedExpressionTree	    |string | Optimized Expression Tree if requested in the query request. Else `null` |
+|runtimePlan    |string     | Runtime plan if requested in the query request. Else `null` |
+|metrics	    |metrics    | Metrics (`compileTime` and `elapsedTime`) if requested in the query request |
+|resultId*  |string     | Result ID of the query submitted for execution. This ID is required later for result fetching |
+|resultUrl* |string     | URL from which the results of the submitted query can be retrieved |
+
+### Result fetching (After an Asynchronous Query Response)
+
+The **resultId** received in the asynchronous query response needs to be submitted as a 
+**path parameter** (`/query/result/${resultId}`) to the REST API in order to retrieve the corresponding results.
+
+| Path | Method |Parameters | Type | Description |
+| ------ | ------ | ------ | ----- |----- |
+| /query/result/${resultId}    | GET | metrics | boolean   | If `true`, returns metrics (compile and execution time) with the response (default: false) |
+
+***
+
+## Error Response
+
+In any of the above scenarios, if an error occurred while processing, REST API will return an *Error Response* as 
+specified below.
+
+| Attribute | Type | Description |
+| ------ | ------ | ------ |
+|status*	|string         | `fatal` to indicate that the query execution was failed at some point | 
+|requestId*	|string         | A unique ID assigned to the request sent |
+|error*     |Error          | An error object which include an error code with an error message. {code: xxx, message: "error message"} |

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-rest/src/site/site.xml
----------------------------------------------------------------------
diff --git a/vxquery-rest/src/site/site.xml b/vxquery-rest/src/site/site.xml
new file mode 100644
index 0000000..bd9b9ab
--- /dev/null
+++ b/vxquery-rest/src/site/site.xml
@@ -0,0 +1,53 @@
+<!--
+  ~ 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.
+  -->
+<project name="VXQuery">
+    <bannerLeft>
+        <name>VXQuery</name>
+        <src>../images/VXQuery.png</src>
+        <href>../index.html</href>
+    </bannerLeft>
+
+    <bannerRight>
+        <name>Apache Software Foundation</name>
+        <src>../images/asf_logo_wide.png</src>
+        <href>http://www.apache.org/</href>
+    </bannerRight>
+
+    <skin>
+        <groupId>org.apache.maven.skins</groupId>
+        <artifactId>maven-fluido-skin</artifactId>
+        <version>1.5</version>
+    </skin>
+
+    <body>
+        <menu name="VXQuery REST API">
+            <item name="Overview" href="index.html"/>
+            <item name="Specification" href="specification.html"/>
+        </menu>
+
+        <menu ref="reports"/>
+        <footer><![CDATA[
+            <div class="row-fluid">Apache VXQuery, VXQuery, Apache, the Apache
+                feather logo, and the Apache VXQuery project logo are either
+                registered trademarks or trademarks of The Apache Software
+                Foundation in the United States and other countries.
+                All other marks mentioned may be trademarks or registered
+                trademarks of their respective owners.
+            </div>]]>
+        </footer>
+    </body>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-rest/src/test/java/org/apache/vxquery/rest/AbstractRestServerTest.java
----------------------------------------------------------------------
diff --git a/vxquery-rest/src/test/java/org/apache/vxquery/rest/AbstractRestServerTest.java b/vxquery-rest/src/test/java/org/apache/vxquery/rest/AbstractRestServerTest.java
new file mode 100644
index 0000000..3d4b124
--- /dev/null
+++ b/vxquery-rest/src/test/java/org/apache/vxquery/rest/AbstractRestServerTest.java
@@ -0,0 +1,225 @@
+/*
+ * 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.vxquery.rest;
+
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.HttpMethod;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.utils.HttpClientUtils;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.vxquery.app.VXQueryApplication;
+import org.apache.vxquery.app.util.LocalClusterUtil;
+import org.apache.vxquery.app.util.RestUtils;
+import org.apache.vxquery.rest.request.QueryRequest;
+import org.apache.vxquery.rest.request.QueryResultRequest;
+import org.apache.vxquery.rest.response.AsyncQueryResponse;
+import org.apache.vxquery.rest.response.QueryResponse;
+import org.apache.vxquery.rest.response.QueryResultResponse;
+import org.apache.vxquery.rest.response.SyncQueryResponse;
+import org.apache.vxquery.rest.service.VXQueryConfig;
+import org.apache.vxquery.rest.service.VXQueryService;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+import io.netty.handler.codec.http.HttpResponseStatus;
+
+/**
+ * Abstract test class to be used for {@link VXQueryApplication} related tests.
+ * These tests are expected to use the REST API for querying and fetching
+ * results
+ *
+ * @author Erandi Ganepola
+ */
+public class AbstractRestServerTest {
+
+    protected static LocalClusterUtil vxqueryLocalCluster = new LocalClusterUtil();
+    protected static String restIpAddress;
+    protected static int restPort;
+    protected static VXQueryService vxQueryService;
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        vxqueryLocalCluster.init(new VXQueryConfig());
+        vxQueryService = vxqueryLocalCluster.getVxQueryService();
+        restIpAddress = vxqueryLocalCluster.getIpAddress();
+        restPort = vxqueryLocalCluster.getRestPort();
+    }
+
+    @AfterClass
+    public static void tearDown() throws Exception {
+        vxqueryLocalCluster.deinit();
+    }
+
+    protected static String normalize(String string) {
+        if (string == null) {
+            return null;
+        }
+
+        return string.replace("\r\n", "").replace("\n", "").replace("\r", "");
+    }
+
+    protected static void checkMetrics(QueryResponse response, boolean showMetrics) {
+        if (showMetrics) {
+            Assert.assertTrue(response.getMetrics().getCompileTime() > 0);
+            Assert.assertTrue(response.getMetrics().getElapsedTime() > 0);
+        } else {
+            Assert.assertTrue(response.getMetrics().getCompileTime() == 0);
+            Assert.assertTrue(response.getMetrics().getElapsedTime() == 0);
+        }
+    }
+
+    protected static void checkResults(AsyncQueryResponse response, boolean compileOnly) {
+        if (compileOnly) {
+            Assert.assertNull(response.getResultUrl());
+            Assert.assertEquals(0, response.getResultId());
+        } else {
+            Assert.assertTrue(response.getResultUrl().startsWith(Constants.RESULT_URL_PREFIX));
+            Assert.assertNotEquals(0, response.getResultId());
+        }
+    }
+
+    protected static void checkResults(SyncQueryResponse response, boolean compileOnly) {
+        if (compileOnly) {
+            Assert.assertNull(response.getResults());
+        } else {
+            Assert.assertNotNull(response.getResults());
+            Assert.assertFalse(response.getResults().isEmpty());
+        }
+    }
+
+    /**
+     * Submit a {@link QueryRequest} and fetth the resulting
+     * {@link AsyncQueryResponse}
+     *
+     * @param uri
+     *            uri of the GET request
+     * @param accepts
+     *            application/json | application/xml
+     * @param method
+     *            Http Method to be used to send the request
+     * @return Response received for the query request
+     * @throws Exception
+     */
+    protected static <T> T getQuerySuccessResponse(URI uri, String accepts, Class<T> type, String method)
+            throws Exception {
+        CloseableHttpClient httpClient = HttpClients.custom().setConnectionTimeToLive(20, TimeUnit.SECONDS).build();
+
+        try {
+            HttpUriRequest request = getRequest(uri, method);
+
+            if (accepts != null) {
+                request.setHeader(HttpHeaders.ACCEPT, accepts);
+            }
+
+            try (CloseableHttpResponse httpResponse = httpClient.execute(request)) {
+                Assert.assertEquals(HttpResponseStatus.OK.code(), httpResponse.getStatusLine().getStatusCode());
+                if (accepts != null) {
+                    Assert.assertEquals(accepts, httpResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue());
+                }
+
+                HttpEntity entity = httpResponse.getEntity();
+                Assert.assertNotNull(entity);
+
+                String response = RestUtils.readEntity(entity);
+                return RestUtils.mapEntity(response, type, accepts);
+            }
+        } finally {
+            HttpClientUtils.closeQuietly(httpClient);
+        }
+    }
+
+    /**
+     * Fetch the {@link QueryResultResponse} from query result endpoint once the
+     * corresponding {@link QueryResultRequest} is given.
+     *
+     * @param resultRequest
+     *            {@link QueryResultRequest}
+     * @param accepts
+     *            expected
+     * 
+     *            <pre>
+     *            Accepts
+     *            </pre>
+     * 
+     *            header in responses
+     * @param method
+     *            Http Method to be used to send the request
+     * @return query result response received
+     * @throws Exception
+     */
+    protected static QueryResultResponse getQueryResultResponse(QueryResultRequest resultRequest, String accepts,
+            String method) throws Exception {
+        URI uri = RestUtils.buildQueryResultURI(resultRequest, restIpAddress, restPort);
+        CloseableHttpClient httpClient = HttpClients.custom().setConnectionTimeToLive(20, TimeUnit.SECONDS).build();
+        try {
+            HttpUriRequest request = getRequest(uri, method);
+
+            if (accepts != null) {
+                request.setHeader(HttpHeaders.ACCEPT, accepts);
+            }
+
+            try (CloseableHttpResponse httpResponse = httpClient.execute(request)) {
+                if (accepts != null) {
+                    Assert.assertEquals(accepts, httpResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue());
+                }
+                Assert.assertEquals(httpResponse.getStatusLine().getStatusCode(), HttpResponseStatus.OK.code());
+
+                HttpEntity entity = httpResponse.getEntity();
+                Assert.assertNotNull(entity);
+
+                String response = RestUtils.readEntity(entity);
+                return RestUtils.mapEntity(response, QueryResultResponse.class, accepts);
+            }
+        } finally {
+            HttpClientUtils.closeQuietly(httpClient);
+        }
+    }
+
+    /**
+     * Creates a POST or GET request accordingly from the given {@link URI}
+     *
+     * @param uri
+     *            URI to which the request us to be sent
+     * @param method
+     *            Http method- GET or POST
+     * @return request
+     */
+    protected static HttpUriRequest getRequest(URI uri, String method) {
+        HttpUriRequest request;
+        switch (method) {
+            case HttpMethod.POST:
+                request = new HttpPost(uri);
+                break;
+            case HttpMethod.GET:
+            default:
+                request = new HttpGet(uri);
+        }
+
+        return request;
+    }
+}

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-rest/src/test/java/org/apache/vxquery/rest/ErrorResponseTest.java
----------------------------------------------------------------------
diff --git a/vxquery-rest/src/test/java/org/apache/vxquery/rest/ErrorResponseTest.java b/vxquery-rest/src/test/java/org/apache/vxquery/rest/ErrorResponseTest.java
new file mode 100644
index 0000000..12b61f3
--- /dev/null
+++ b/vxquery-rest/src/test/java/org/apache/vxquery/rest/ErrorResponseTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.vxquery.rest;
+
+import static org.apache.vxquery.app.util.RestUtils.buildQueryResultURI;
+import static org.apache.vxquery.app.util.RestUtils.buildQueryURI;
+import static org.apache.vxquery.rest.Constants.ErrorCodes.INVALID_INPUT;
+import static org.apache.vxquery.rest.Constants.ErrorCodes.NOT_FOUND;
+import static org.apache.vxquery.rest.Constants.ErrorCodes.PROBLEM_WITH_QUERY;
+import static org.apache.vxquery.rest.Constants.HttpHeaderValues.CONTENT_TYPE_JSON;
+import static org.apache.vxquery.rest.Constants.HttpHeaderValues.CONTENT_TYPE_XML;
+
+import java.net.URI;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.HttpMethod;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.utils.HttpClientUtils;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.vxquery.app.util.RestUtils;
+import org.apache.vxquery.rest.request.QueryRequest;
+import org.apache.vxquery.rest.request.QueryResultRequest;
+import org.apache.vxquery.rest.response.ErrorResponse;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests error codes of the possible error responses that can be received for
+ * erroneous queries.
+ *
+ * @author Erandi Ganepola
+ */
+public class ErrorResponseTest extends AbstractRestServerTest {
+
+    @Test
+    public void testInvalidInput01() throws Exception {
+        QueryRequest request = new QueryRequest("   ");
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, INVALID_INPUT);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, INVALID_INPUT);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, INVALID_INPUT);
+    }
+
+    @Test
+    public void testInvalidInput02() throws Exception {
+        QueryRequest request = new QueryRequest("");
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, 405);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, 405);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, 405);
+    }
+
+    @Test
+    public void testInvalidQuery01() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1,2,3) return $y");
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, PROBLEM_WITH_QUERY);
+    }
+
+    @Test
+    public void testInvalidQuery02() throws Exception {
+        QueryRequest request = new QueryRequest("for x in (1,2,3) return $x");
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, PROBLEM_WITH_QUERY);
+    }
+
+    @Test
+    public void testInvalidQuery03() throws Exception {
+        QueryRequest request = new QueryRequest("insert nodes <book></book> into doc(\"abcd.xml\")/books");
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, PROBLEM_WITH_QUERY);
+    }
+
+    @Test
+    public void testInvalidQuery04() throws Exception {
+        QueryRequest request = new QueryRequest("delete nodes /a/b//node()");
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, PROBLEM_WITH_QUERY);
+    }
+
+    @Test
+    public void testInvalidResultId() throws Exception {
+        QueryResultRequest request = new QueryResultRequest(1000);
+        runTest(buildQueryResultURI(request, restIpAddress, restPort), null, NOT_FOUND);
+        runTest(buildQueryResultURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, NOT_FOUND);
+        runTest(buildQueryResultURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, NOT_FOUND);
+    }
+
+    @Test
+    public void testSyncInvalidInput01() throws Exception {
+        QueryRequest request = new QueryRequest("   ");
+        request.setAsync(false);
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, INVALID_INPUT);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, INVALID_INPUT);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, INVALID_INPUT);
+    }
+
+    @Test
+    public void testSyncInvalidInput02() throws Exception {
+        QueryRequest request = new QueryRequest("");
+        request.setAsync(false);
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, 405);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, 405);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, 405);
+    }
+
+    @Test
+    public void testSyncInvalidQuery01() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1,2,3) return $y");
+        request.setAsync(false);
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, PROBLEM_WITH_QUERY);
+    }
+
+    @Test
+    public void testSyncInvalidQuery02() throws Exception {
+        QueryRequest request = new QueryRequest("for x in (1,2,3) return $x");
+        request.setAsync(false);
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, PROBLEM_WITH_QUERY);
+    }
+
+    @Test
+    public void testSyncInvalidQuery03() throws Exception {
+        QueryRequest request = new QueryRequest("insert nodes <book></book> into doc(\"abcd.xml\")/books");
+        request.setAsync(false);
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, PROBLEM_WITH_QUERY);
+    }
+
+    @Test
+    public void testSyncInvalidQuery04() throws Exception {
+        QueryRequest request = new QueryRequest("delete nodes /a/b//node()");
+        request.setAsync(false);
+        runTest(buildQueryURI(request, restIpAddress, restPort), null, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_JSON, PROBLEM_WITH_QUERY);
+        runTest(buildQueryURI(request, restIpAddress, restPort), CONTENT_TYPE_XML, PROBLEM_WITH_QUERY);
+    }
+
+    private void runTest(URI uri, String accepts, int expectedStatusCode) throws Exception {
+        runTest(uri, accepts, expectedStatusCode, HttpMethod.GET);
+        runTest(uri, accepts, expectedStatusCode, HttpMethod.POST);
+    }
+
+    private void runTest(URI uri, String accepts, int expectedStatusCode, String httpMethod) throws Exception {
+        CloseableHttpClient httpClient = HttpClients.custom().setConnectionTimeToLive(20, TimeUnit.SECONDS).build();
+
+        ErrorResponse errorResponse;
+        try {
+            HttpUriRequest request = getRequest(uri, httpMethod);
+            if (accepts != null) {
+                request.setHeader(HttpHeaders.ACCEPT, accepts);
+            }
+
+            try (CloseableHttpResponse httpResponse = httpClient.execute(request)) {
+                Assert.assertEquals(expectedStatusCode, httpResponse.getStatusLine().getStatusCode());
+                if (accepts != null) {
+                    Assert.assertEquals(accepts, httpResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue());
+                }
+
+                HttpEntity entity = httpResponse.getEntity();
+                Assert.assertNotNull(entity);
+
+                String response = RestUtils.readEntity(entity);
+                errorResponse = RestUtils.mapEntity(response, ErrorResponse.class, accepts);
+            }
+        } finally {
+            HttpClientUtils.closeQuietly(httpClient);
+        }
+
+        Assert.assertNotNull(errorResponse);
+        Assert.assertNotNull(errorResponse.getError().getMessage());
+        Assert.assertEquals(errorResponse.getError().getCode(), expectedStatusCode);
+    }
+}

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-rest/src/test/java/org/apache/vxquery/rest/SuccessAsyncResponseTest.java
----------------------------------------------------------------------
diff --git a/vxquery-rest/src/test/java/org/apache/vxquery/rest/SuccessAsyncResponseTest.java b/vxquery-rest/src/test/java/org/apache/vxquery/rest/SuccessAsyncResponseTest.java
new file mode 100644
index 0000000..d1385c8
--- /dev/null
+++ b/vxquery-rest/src/test/java/org/apache/vxquery/rest/SuccessAsyncResponseTest.java
@@ -0,0 +1,289 @@
+/*
+ * 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.vxquery.rest;
+
+import static org.apache.vxquery.rest.Constants.HttpHeaderValues.CONTENT_TYPE_JSON;
+import static org.apache.vxquery.rest.Constants.HttpHeaderValues.CONTENT_TYPE_XML;
+
+import java.net.URI;
+
+import javax.ws.rs.HttpMethod;
+
+import org.apache.vxquery.app.util.RestUtils;
+import org.apache.vxquery.rest.request.QueryRequest;
+import org.apache.vxquery.rest.request.QueryResultRequest;
+import org.apache.vxquery.rest.response.APIResponse;
+import org.apache.vxquery.rest.response.AsyncQueryResponse;
+import org.apache.vxquery.rest.response.ErrorResponse;
+import org.apache.vxquery.rest.response.QueryResultResponse;
+import org.apache.vxquery.rest.service.Status;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * This class tests the success responses received for XQueries submitted. i.e
+ * we are submitting correct queries which are expected to return a predictable
+ * result. All the parameters that are expected to be sent with query requests
+ * are subjected to test in this test class
+ *
+ * @author Erandi Ganepola
+ */
+public class SuccessAsyncResponseTest extends AbstractRestServerTest {
+
+    @Test
+    public void testSimpleQuery001() throws Exception {
+        QueryRequest request = new QueryRequest("1+1");
+        request.setShowAbstractSyntaxTree(true);
+        request.setShowOptimizedExpressionTree(true);
+        request.setShowRuntimePlan(true);
+        request.setShowTranslatedExpressionTree(true);
+        request.setShowMetrics(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSimpleQuery002() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setShowAbstractSyntaxTree(true);
+        request.setShowOptimizedExpressionTree(true);
+        request.setShowRuntimePlan(true);
+        request.setShowTranslatedExpressionTree(true);
+        request.setShowMetrics(true);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSimpleQuery003() throws Exception {
+        QueryRequest request = new QueryRequest("1+2+3");
+        request.setShowAbstractSyntaxTree(false);
+        request.setShowOptimizedExpressionTree(false);
+        request.setShowRuntimePlan(false);
+        request.setShowTranslatedExpressionTree(false);
+        request.setShowMetrics(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSimpleQuery004() throws Exception {
+        QueryRequest request = new QueryRequest("fn:true()");
+        request.setShowAbstractSyntaxTree(false);
+        request.setShowOptimizedExpressionTree(false);
+        request.setShowRuntimePlan(true);
+        request.setShowTranslatedExpressionTree(false);
+        request.setShowMetrics(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterNone() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterMetrics() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setShowMetrics(true);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterAST() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setShowAbstractSyntaxTree(true);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterOptimization() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setOptimization(10000);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterFrameSize() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setFrameSize((int) Math.pow(2, 12));
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterCompileOnly() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setCompileOnly(true);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterOET() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setShowOptimizedExpressionTree(true);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterTET() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setShowTranslatedExpressionTree(true);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterRP() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setShowRuntimePlan(true);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    private void runTest(String contentType, QueryRequest request) throws Exception {
+        runTest(contentType, request, HttpMethod.GET);
+        runTest(contentType, request, HttpMethod.POST);
+    }
+
+    private void runTest(String contentType, QueryRequest request, String httpMethod) throws Exception {
+        URI queryEndpointUri = RestUtils.buildQueryURI(request, restIpAddress, restPort);
+
+        /*
+         * ========== Query Response Testing ==========
+         */
+        // Testing the accuracy of VXQueryService class
+        AsyncQueryResponse expectedAsyncQueryResponse = (AsyncQueryResponse) vxQueryService.execute(request);
+
+        Assert.assertEquals(Status.SUCCESS.toString(), expectedAsyncQueryResponse.getStatus());
+        Assert.assertEquals(request.getStatement(), expectedAsyncQueryResponse.getStatement());
+        checkResults(expectedAsyncQueryResponse, request.isCompileOnly());
+        checkMetrics(expectedAsyncQueryResponse, request.isShowMetrics());
+        if (request.isShowMetrics()) {
+            Assert.assertTrue(expectedAsyncQueryResponse.getMetrics().getCompileTime() > 0);
+        } else {
+            Assert.assertTrue(expectedAsyncQueryResponse.getMetrics().getCompileTime() == 0);
+        }
+        if (request.isShowAbstractSyntaxTree()) {
+            Assert.assertNotNull(expectedAsyncQueryResponse.getAbstractSyntaxTree());
+        } else {
+            Assert.assertNull(expectedAsyncQueryResponse.getAbstractSyntaxTree());
+        }
+        if (request.isShowTranslatedExpressionTree()) {
+            Assert.assertNotNull(expectedAsyncQueryResponse.getTranslatedExpressionTree());
+        } else {
+            Assert.assertNull(expectedAsyncQueryResponse.getTranslatedExpressionTree());
+        }
+        if (request.isShowOptimizedExpressionTree()) {
+            Assert.assertNotNull(expectedAsyncQueryResponse.getOptimizedExpressionTree());
+        } else {
+            Assert.assertNull(expectedAsyncQueryResponse.getOptimizedExpressionTree());
+        }
+        if (request.isShowRuntimePlan()) {
+            Assert.assertNotNull(expectedAsyncQueryResponse.getRuntimePlan());
+        } else {
+            Assert.assertNull(expectedAsyncQueryResponse.getRuntimePlan());
+        }
+
+        // Testing the accuracy of REST server and servlets
+        AsyncQueryResponse actualAsyncQueryResponse =
+                getQuerySuccessResponse(queryEndpointUri, contentType, AsyncQueryResponse.class, httpMethod);
+
+        Assert.assertNotNull(actualAsyncQueryResponse.getRequestId());
+        Assert.assertEquals(request.getStatement(), actualAsyncQueryResponse.getStatement());
+        Assert.assertEquals(Status.SUCCESS.toString(), actualAsyncQueryResponse.getStatus());
+        checkResults(actualAsyncQueryResponse, request.isCompileOnly());
+        checkMetrics(actualAsyncQueryResponse, request.isShowMetrics());
+        // Cannot check this because Runtime plan include some object IDs which differ
+        // Assert.assertEquals(expectedAsyncQueryResponse.getRuntimePlan(),
+        // actualAsyncQueryResponse.getRuntimePlan());
+        if (request.isShowRuntimePlan()) {
+            Assert.assertNotNull(actualAsyncQueryResponse.getRuntimePlan());
+        } else {
+            Assert.assertNull(actualAsyncQueryResponse.getRuntimePlan());
+        }
+        Assert.assertEquals(normalize(expectedAsyncQueryResponse.getOptimizedExpressionTree()),
+                normalize(actualAsyncQueryResponse.getOptimizedExpressionTree()));
+        Assert.assertEquals(normalize(expectedAsyncQueryResponse.getTranslatedExpressionTree()),
+                normalize(actualAsyncQueryResponse.getTranslatedExpressionTree()));
+        Assert.assertEquals(normalize(expectedAsyncQueryResponse.getAbstractSyntaxTree()),
+                normalize(actualAsyncQueryResponse.getAbstractSyntaxTree()));
+
+        /*
+         * ========== Query Result Response Testing ========
+         */
+        QueryResultRequest resultRequest = new QueryResultRequest(actualAsyncQueryResponse.getResultId());
+        resultRequest.setShowMetrics(true);
+
+        if (request.isCompileOnly()) {
+            APIResponse resultResponse = vxQueryService.getResult(resultRequest);
+            Assert.assertTrue(resultResponse instanceof ErrorResponse);
+        } else {
+            QueryResultResponse expectedResultResponse = (QueryResultResponse) vxQueryService.getResult(resultRequest);
+            Assert.assertEquals(expectedResultResponse.getStatus(), Status.SUCCESS.toString());
+            Assert.assertNotNull(expectedResultResponse.getResults());
+
+            QueryResultResponse actualResultResponse = getQueryResultResponse(resultRequest, contentType, httpMethod);
+            Assert.assertEquals(actualResultResponse.getStatus(), Status.SUCCESS.toString());
+            Assert.assertNotNull(actualResultResponse.getResults());
+            Assert.assertNotNull(actualResultResponse.getRequestId());
+            Assert.assertEquals(normalize(expectedResultResponse.getResults()),
+                    normalize(actualResultResponse.getResults()));
+            if (resultRequest.isShowMetrics()) {
+                Assert.assertTrue(actualResultResponse.getMetrics().getElapsedTime() > 0);
+            } else {
+                Assert.assertTrue(actualResultResponse.getMetrics().getElapsedTime() == 0);
+            }
+
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-rest/src/test/java/org/apache/vxquery/rest/SuccessSyncResponseTest.java
----------------------------------------------------------------------
diff --git a/vxquery-rest/src/test/java/org/apache/vxquery/rest/SuccessSyncResponseTest.java b/vxquery-rest/src/test/java/org/apache/vxquery/rest/SuccessSyncResponseTest.java
new file mode 100644
index 0000000..31e0162
--- /dev/null
+++ b/vxquery-rest/src/test/java/org/apache/vxquery/rest/SuccessSyncResponseTest.java
@@ -0,0 +1,215 @@
+/*
+ * 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.vxquery.rest;
+
+import static org.apache.vxquery.rest.Constants.HttpHeaderValues.CONTENT_TYPE_JSON;
+import static org.apache.vxquery.rest.Constants.HttpHeaderValues.CONTENT_TYPE_XML;
+
+import java.net.URI;
+
+import javax.ws.rs.HttpMethod;
+
+import org.apache.vxquery.app.util.RestUtils;
+import org.apache.vxquery.rest.request.QueryRequest;
+import org.apache.vxquery.rest.response.SyncQueryResponse;
+import org.apache.vxquery.rest.service.Status;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * This class tests the success responses received for XQueries submitted. i.e
+ * we are submitting correct queries which are expected to return a predictable
+ * result. All the parameters that are expected to be sent with query requests
+ * are subjected to test in this test class
+ *
+ * @author Erandi Ganepola
+ */
+public class SuccessSyncResponseTest extends AbstractRestServerTest {
+
+    @Test
+    public void testSimpleQuery001() throws Exception {
+        QueryRequest request = new QueryRequest("1+1");
+        request.setShowAbstractSyntaxTree(true);
+        request.setShowOptimizedExpressionTree(true);
+        request.setShowRuntimePlan(true);
+        request.setShowTranslatedExpressionTree(true);
+        request.setShowMetrics(false);
+        request.setAsync(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSimpleQuery002() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setShowAbstractSyntaxTree(true);
+        request.setShowOptimizedExpressionTree(true);
+        request.setShowRuntimePlan(true);
+        request.setShowTranslatedExpressionTree(true);
+        request.setShowMetrics(true);
+        request.setAsync(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSimpleQuery003() throws Exception {
+        QueryRequest request = new QueryRequest("1+2+3");
+        request.setShowAbstractSyntaxTree(false);
+        request.setShowOptimizedExpressionTree(false);
+        request.setShowRuntimePlan(false);
+        request.setShowTranslatedExpressionTree(false);
+        request.setShowMetrics(false);
+        request.setAsync(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSimpleQuery004() throws Exception {
+        QueryRequest request = new QueryRequest("fn:true()");
+        request.setShowAbstractSyntaxTree(false);
+        request.setShowOptimizedExpressionTree(false);
+        request.setShowRuntimePlan(true);
+        request.setShowTranslatedExpressionTree(false);
+        request.setShowMetrics(false);
+        request.setAsync(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterNone() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setAsync(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterCompileOnly() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setCompileOnly(true);
+        request.setAsync(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    @Test
+    public void testSingleParameterRepeatExecutions() throws Exception {
+        QueryRequest request = new QueryRequest("for $x in (1, 2.0, 3) return $x");
+        request.setRepeatExecutions(5);
+        request.setAsync(false);
+
+        runTest(null, request);
+        runTest(CONTENT_TYPE_JSON, request);
+        runTest(CONTENT_TYPE_XML, request);
+    }
+
+    private void runTest(String contentType, QueryRequest request) throws Exception {
+        runTest(contentType, request, HttpMethod.GET);
+        runTest(contentType, request, HttpMethod.POST);
+    }
+
+    private void runTest(String contentType, QueryRequest request, String httpMethod) throws Exception {
+        URI queryEndpointUri = RestUtils.buildQueryURI(request, restIpAddress, restPort);
+
+        /*
+         * ========== Query Response Testing ==========
+         */
+        // Testing the accuracy of VXQueryService class
+        SyncQueryResponse expectedSyncQueryResponse = (SyncQueryResponse) vxQueryService.execute(request);
+
+        Assert.assertEquals(Status.SUCCESS.toString(), expectedSyncQueryResponse.getStatus());
+        Assert.assertEquals(request.getStatement(), expectedSyncQueryResponse.getStatement());
+        checkResults(expectedSyncQueryResponse, request.isCompileOnly());
+        checkMetrics(expectedSyncQueryResponse, request.isShowMetrics());
+        if (request.isShowMetrics()) {
+            Assert.assertTrue(expectedSyncQueryResponse.getMetrics().getCompileTime() > 0);
+        } else {
+            Assert.assertTrue(expectedSyncQueryResponse.getMetrics().getCompileTime() == 0);
+        }
+        if (request.isShowAbstractSyntaxTree()) {
+            Assert.assertNotNull(expectedSyncQueryResponse.getAbstractSyntaxTree());
+        } else {
+            Assert.assertNull(expectedSyncQueryResponse.getAbstractSyntaxTree());
+        }
+        if (request.isShowTranslatedExpressionTree()) {
+            Assert.assertNotNull(expectedSyncQueryResponse.getTranslatedExpressionTree());
+        } else {
+            Assert.assertNull(expectedSyncQueryResponse.getTranslatedExpressionTree());
+        }
+        if (request.isShowOptimizedExpressionTree()) {
+            Assert.assertNotNull(expectedSyncQueryResponse.getOptimizedExpressionTree());
+        } else {
+            Assert.assertNull(expectedSyncQueryResponse.getOptimizedExpressionTree());
+        }
+        if (request.isShowRuntimePlan()) {
+            Assert.assertNotNull(expectedSyncQueryResponse.getRuntimePlan());
+        } else {
+            Assert.assertNull(expectedSyncQueryResponse.getRuntimePlan());
+        }
+
+        // Testing the accuracy of REST server and servlets
+        SyncQueryResponse actualSyncQueryResponse =
+                getQuerySuccessResponse(queryEndpointUri, contentType, SyncQueryResponse.class, httpMethod);
+
+        Assert.assertNotNull(actualSyncQueryResponse.getRequestId());
+        Assert.assertEquals(request.getStatement(), actualSyncQueryResponse.getStatement());
+        Assert.assertEquals(Status.SUCCESS.toString(), actualSyncQueryResponse.getStatus());
+        checkMetrics(actualSyncQueryResponse, request.isShowMetrics());
+        checkResults(actualSyncQueryResponse, request.isCompileOnly());
+        // Cannot check this because Runtime plan include some object IDs which differ
+        // Assert.assertEquals(expectedSyncQueryResponse.getRuntimePlan(),
+        // actualSyncQueryResponse.getRuntimePlan());
+        if (request.isShowRuntimePlan()) {
+            Assert.assertNotNull(actualSyncQueryResponse.getRuntimePlan());
+        } else {
+            Assert.assertNull(actualSyncQueryResponse.getRuntimePlan());
+        }
+        Assert.assertEquals(normalize(expectedSyncQueryResponse.getOptimizedExpressionTree()),
+                normalize(actualSyncQueryResponse.getOptimizedExpressionTree()));
+        Assert.assertEquals(normalize(expectedSyncQueryResponse.getTranslatedExpressionTree()),
+                normalize(actualSyncQueryResponse.getTranslatedExpressionTree()));
+        Assert.assertEquals(normalize(expectedSyncQueryResponse.getAbstractSyntaxTree()),
+                normalize(actualSyncQueryResponse.getAbstractSyntaxTree()));
+
+        /*
+         * ========== Query Result Response Testing ========
+         */
+        String expectedResults = expectedSyncQueryResponse.getResults();
+        String actualResults = actualSyncQueryResponse.getResults();
+        if (!request.isCompileOnly()) {
+            Assert.assertNotNull(expectedResults);
+            Assert.assertNotNull(actualResults);
+        }
+        Assert.assertEquals(normalize(expectedResults), normalize(actualResults));
+    }
+}

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-rest/src/test/resources/vxquery.properties
----------------------------------------------------------------------
diff --git a/vxquery-rest/src/test/resources/vxquery.properties b/vxquery-rest/src/test/resources/vxquery.properties
new file mode 100644
index 0000000..8870f79
--- /dev/null
+++ b/vxquery-rest/src/test/resources/vxquery.properties
@@ -0,0 +1,30 @@
+#
+# 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.
+
+# Number of processors to be used for query processing
+#org.apache.vxquery.available_processors=-1
+
+# Number of local node controllers to be created when creating a local hyracks cluster
+org.apache.vxquery.local_nc=1
+
+# Join hash size
+#org.apache.vxquery.join_hash=-1
+
+# Maximum Data Size
+#org.apache.vxquery.data_size=-1
+
+# hdfs config directory
+#org.apache.vxquery.hdfs_config=foo/bar

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-server/pom.xml
----------------------------------------------------------------------
diff --git a/vxquery-server/pom.xml b/vxquery-server/pom.xml
index e572c36..7331fde 100644
--- a/vxquery-server/pom.xml
+++ b/vxquery-server/pom.xml
@@ -41,7 +41,7 @@
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>appassembler-maven-plugin</artifactId>
-                <version>1.1.1</version>
+                <version>2.0.0</version>
                 <executions>
                     <execution>
                         <configuration>
@@ -53,6 +53,10 @@
                                 <program>
                                     <mainClass>org.apache.hyracks.control.cc.CCDriver</mainClass>
                                     <name>vxquerycc</name>
+                                    <commandLineArguments>
+                                        <commandLineArgument>-app-cc-main-class</commandLineArgument>
+                                        <commandLineArgument>org.apache.vxquery.app.VXQueryApplication</commandLineArgument>
+                                    </commandLineArguments>
                                 </program>
                                 <program>
                                     <mainClass>org.apache.hyracks.control.nc.NCDriver</mainClass>
@@ -139,15 +143,13 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.vxquery</groupId>
-            <artifactId>apache-vxquery-core</artifactId>
+            <artifactId>apache-vxquery-rest</artifactId>
             <version>0.7-SNAPSHOT</version>
         </dependency>
-
         <dependency>
             <groupId>org.apache.hyracks</groupId>
             <artifactId>hyracks-control-cc</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.apache.hyracks</groupId>
             <artifactId>hyracks-control-nc</artifactId>

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-xtest/pom.xml
----------------------------------------------------------------------
diff --git a/vxquery-xtest/pom.xml b/vxquery-xtest/pom.xml
index a00bec2..a32d913 100644
--- a/vxquery-xtest/pom.xml
+++ b/vxquery-xtest/pom.xml
@@ -144,6 +144,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.vxquery</groupId>
+            <artifactId>apache-vxquery-rest</artifactId>
+            <version>0.7-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
             <groupId>org.apache.hyracks</groupId>
             <artifactId>hyracks-api</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestClusterUtil.java
----------------------------------------------------------------------
diff --git a/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestClusterUtil.java b/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestClusterUtil.java
index 0e5b481..4d2ae8a 100644
--- a/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestClusterUtil.java
+++ b/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestClusterUtil.java
@@ -19,81 +19,45 @@ package org.apache.vxquery.xtest;
 
 import org.apache.hyracks.api.client.HyracksConnection;
 import org.apache.hyracks.client.dataset.HyracksDataset;
-import org.apache.hyracks.control.cc.ClusterControllerService;
-import org.apache.hyracks.control.common.controllers.CCConfig;
-import org.apache.hyracks.control.common.controllers.NCConfig;
-import org.apache.hyracks.control.nc.NodeControllerService;
+import org.apache.vxquery.app.util.LocalClusterUtil;
+import org.apache.vxquery.rest.service.VXQueryConfig;
 
-import java.io.File;
 import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 
 public class TestClusterUtil {
 
-    private static final int CLIENT_NET_PORT = 39000;
-    private static final int CLUSTER_NET_PORT = 39001;
-    private static final int PROFILE_DUMP_PERIOD = 10000;
-    private static final String CC_HOST = "localhost";
-    private static final String NODE_ID = "nc1";
-    private static final String IO_DEVICES = "target/tmp/indexFolder";
-
     private static HyracksConnection hcc;
     private static HyracksDataset hds;
 
+    public static final LocalClusterUtil localClusterUtil = new LocalClusterUtil();
+
     private TestClusterUtil() {
     }
 
-    public static CCConfig createCCConfig() throws UnknownHostException {
-        String publicAddress = InetAddress.getLocalHost().getHostAddress();
-        CCConfig ccConfig = new CCConfig();
-        ccConfig.clientNetIpAddress = publicAddress;
-        ccConfig.clientNetPort = CLIENT_NET_PORT;
-        ccConfig.clusterNetIpAddress = publicAddress;
-        ccConfig.clusterNetPort = CLUSTER_NET_PORT;
-        ccConfig.profileDumpPeriod = PROFILE_DUMP_PERIOD;
-        return ccConfig;
-    }
+    private static VXQueryConfig loadConfiguration(XTestOptions opts) {
+        VXQueryConfig vxqConfig = new VXQueryConfig();
 
-    public static NCConfig createNCConfig() throws UnknownHostException {
-        String publicAddress = InetAddress.getLocalHost().getHostAddress();
-        NCConfig ncConfig1 = new NCConfig();
-        ncConfig1.ccHost = CC_HOST;
-        ncConfig1.ccPort = CLUSTER_NET_PORT;
-        ncConfig1.clusterNetIPAddress = publicAddress;
-        ncConfig1.dataIPAddress = publicAddress;
-        ncConfig1.resultIPAddress = publicAddress;
-        ncConfig1.nodeId = NODE_ID;
-        ncConfig1.ioDevices = IO_DEVICES;
-        return ncConfig1;
+        vxqConfig.setAvailableProcessors(opts.threads);
+        vxqConfig.setFrameSize(opts.frameSize);
+        vxqConfig.setHdfsConf(opts.hdfsConf);
+
+        return vxqConfig;
     }
 
-    public static ClusterControllerService startCC(XTestOptions opts) throws IOException {
-        CCConfig ccConfig = createCCConfig();
-        File outDir = new File("target/ClusterController");
-        outDir.mkdirs();
-        File ccRoot = File.createTempFile(TestRunner.class.getName(), ".data", outDir);
-        ccRoot.delete();
-        ccRoot.mkdir();
-        ccConfig.ccRoot = ccRoot.getAbsolutePath();
+    public static void startCluster(XTestOptions opts, LocalClusterUtil localClusterUtil) throws IOException {
         try {
-            ClusterControllerService cc = new ClusterControllerService(ccConfig);
-            cc.start();
-            hcc = new HyracksConnection(ccConfig.clientNetIpAddress, ccConfig.clientNetPort);
-            hds = new HyracksDataset(hcc, opts.frameSize, opts.threads);
-            return cc;
+            VXQueryConfig config = loadConfiguration(opts);
+            localClusterUtil.init(config);
+            hcc = (HyracksConnection) localClusterUtil.getConnection();
+            hds = (HyracksDataset) localClusterUtil.getDataset();
         } catch (Exception e) {
             throw new IOException(e);
         }
-
     }
 
-    public static NodeControllerService startNC() throws IOException {
-        NCConfig ncConfig = createNCConfig();
+    public static void stopCluster(LocalClusterUtil localClusterUtil) throws IOException {
         try {
-            NodeControllerService nc = new NodeControllerService(ncConfig);
-            nc.start();
-            return nc;
+            localClusterUtil.deinit();
         } catch (Exception e) {
             throw new IOException(e);
         }
@@ -107,13 +71,4 @@ public class TestClusterUtil {
         return hds;
     }
 
-    public static void stopCluster(ClusterControllerService cc, NodeControllerService nc) throws IOException {
-        try {
-            nc.stop();
-            cc.stop();
-        } catch (Exception e) {
-            throw new IOException(e);
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestRunner.java
----------------------------------------------------------------------
diff --git a/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestRunner.java b/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestRunner.java
index fa0a900..8ef9426 100644
--- a/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestRunner.java
+++ b/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/TestRunner.java
@@ -14,101 +14,54 @@
  */
 package org.apache.vxquery.xtest;
 
+import static org.apache.vxquery.rest.Constants.HttpHeaderValues.CONTENT_TYPE_JSON;
+
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.List;
+import java.nio.charset.StandardCharsets;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.api.client.NodeControllerInfo;
-import org.apache.hyracks.api.comm.IFrame;
-import org.apache.hyracks.api.comm.IFrameTupleAccessor;
-import org.apache.hyracks.api.comm.VSizeFrame;
-import org.apache.hyracks.api.dataset.DatasetJobRecord;
-import org.apache.hyracks.api.dataset.IHyracksDataset;
-import org.apache.hyracks.api.dataset.IHyracksDatasetReader;
-import org.apache.hyracks.api.dataset.ResultSetId;
-import org.apache.hyracks.api.exceptions.HyracksException;
-import org.apache.hyracks.api.job.JobFlag;
-import org.apache.hyracks.api.job.JobId;
-import org.apache.hyracks.api.job.JobSpecification;
-import org.apache.hyracks.control.nc.resources.memory.FrameManager;
-import org.apache.hyracks.dataflow.common.comm.io.ResultFrameTupleAccessor;
-import org.apache.vxquery.compiler.CompilerControlBlock;
-import org.apache.vxquery.compiler.algebricks.VXQueryGlobalDataFactory;
-import org.apache.vxquery.context.DynamicContext;
-import org.apache.vxquery.context.DynamicContextImpl;
-import org.apache.vxquery.context.RootStaticContextImpl;
-import org.apache.vxquery.context.StaticContextImpl;
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.HttpClientUtils;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.vxquery.app.util.RestUtils;
 import org.apache.vxquery.exceptions.ErrorCode;
 import org.apache.vxquery.exceptions.SystemException;
-import org.apache.vxquery.result.ResultUtils;
-import org.apache.vxquery.xmlquery.query.VXQueryCompilationListener;
-import org.apache.vxquery.xmlquery.query.XMLQueryCompiler;
+import org.apache.vxquery.rest.request.QueryRequest;
+import org.apache.vxquery.rest.response.APIResponse;
+import org.apache.vxquery.rest.response.ErrorResponse;
+import org.apache.vxquery.rest.response.SyncQueryResponse;
+import org.codehaus.jackson.map.ObjectMapper;
 
 public class TestRunner {
+
     private static final Pattern EMBEDDED_SYSERROR_PATTERN = Pattern.compile("(\\p{javaUpperCase}{4}\\d{4})");
-    private List<String> collectionList;
+
     private XTestOptions opts;
-    private IHyracksClientConnection hcc;
-    private IHyracksDataset hds;
 
     public TestRunner(XTestOptions opts) throws UnknownHostException {
         this.opts = opts;
-        this.collectionList = new ArrayList<String>();
     }
 
     public void open() throws Exception {
-        hcc = TestClusterUtil.getConnection();
-        hds = TestClusterUtil.getDataset();
-    }
-
-    protected static TestConfiguration getIndexConfiguration(TestCase testCase) {
-        XTestOptions opts = new XTestOptions();
-        opts.verbose = false;
-        opts.threads = 1;
-        opts.showQuery = true;
-        opts.showResult = true;
-        opts.hdfsConf = "src/test/resources/hadoop/conf";
-        opts.catalog = StringUtils.join(new String[] { "src", "test", "resources", "VXQueryCatalog.xml" },
-                File.separator);
-        TestConfiguration indexConf = new TestConfiguration();
-        indexConf.options = opts;
-        String baseDir = new File(opts.catalog).getParent();
-        try {
-            String root = new File(baseDir).getCanonicalPath();
-            indexConf.testRoot = new File(root + "/./");
-            indexConf.resultOffsetPath = new File(root + "/./ExpectedResults/");
-            indexConf.sourceFileMap = testCase.getSourceFileMap();
-            indexConf.xqueryFileExtension = ".xq";
-            indexConf.xqueryxFileExtension = "xqx";
-            indexConf.xqueryQueryOffsetPath = new File(root + "/./Queries/XQuery/");
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return indexConf;
-
     }
 
     public TestCaseResult run(final TestCase testCase) {
         TestCaseResult res = new TestCaseResult(testCase);
-        TestCase testCaseIndex = new TestCase(getIndexConfiguration(testCase));
-        testCaseIndex.setFolder("Indexing/Partition-1/");
-        testCaseIndex.setName("showIndexes");
-        runQuery(testCaseIndex, res);
-        String[] collections = res.result.split("\n");
-        this.collectionList = Arrays.asList(collections);
         runQueries(testCase, res);
         return res;
     }
@@ -121,83 +74,32 @@ public class TestRunner {
         long start = System.currentTimeMillis();
 
         try {
-            try {
-                if (opts.showQuery) {
+            String query = FileUtils.readFileToString(testCase.getXQueryFile(), "UTF-8");
 
-                    FileInputStream query = new FileInputStream(testCase.getXQueryFile());
-                    System.err.println("***Query for " + testCase.getXQueryDisplayName() + ": ");
-                    System.err.println(IOUtils.toString(query, "UTF-8"));
-                    query.close();
-                }
-
-                VXQueryCompilationListener listener = new VXQueryCompilationListener(opts.showAST, opts.showTET,
-                        opts.showOET, opts.showRP);
-
-                Map<String, NodeControllerInfo> nodeControllerInfos = null;
-                if (hcc != null) {
-                    nodeControllerInfos = hcc.getNodeControllerInfos();
-                }
+            if (opts.showQuery) {
+                System.err.println("***Query for " + testCase.getXQueryDisplayName() + ": ");
+                System.err.println(query);
+            }
 
-                XMLQueryCompiler compiler = new XMLQueryCompiler(listener, nodeControllerInfos, opts.frameSize,
-                        opts.hdfsConf);
-                Reader in = new InputStreamReader(new FileInputStream(testCase.getXQueryFile()), "UTF-8");
-                CompilerControlBlock ccb = new CompilerControlBlock(
-                        new StaticContextImpl(RootStaticContextImpl.INSTANCE),
-                        new ResultSetId(testCase.getXQueryDisplayName().hashCode()), testCase.getSourceFileMap());
-                compiler.compile(testCase.getXQueryDisplayName(), in, ccb, opts.optimizationLevel, collectionList);
-                JobSpecification spec = compiler.getModule().getHyracksJobSpecification();
-                in.close();
-
-                DynamicContext dCtx = new DynamicContextImpl(compiler.getModule().getModuleContext());
-                spec.setGlobalJobDataFactory(new VXQueryGlobalDataFactory(dCtx.createFactory()));
-
-                spec.setMaxReattempts(0);
-                JobId jobId = hcc.startJob(spec, EnumSet.of(JobFlag.PROFILE_RUNTIME));
-
-                FrameManager resultDisplayFrameMgr = new FrameManager(spec.getFrameSize());
-                IFrame frame = new VSizeFrame(resultDisplayFrameMgr);
-                IHyracksDatasetReader reader = hds.createReader(jobId, ccb.getResultSetId());
-                // TODO(tillw) remove this loop once the IHyracksDatasetReader reliably returns the correct exception
-                while (reader.getResultStatus() == DatasetJobRecord.Status.RUNNING) {
-                    Thread.sleep(1);
-                }
-                IFrameTupleAccessor frameTupleAccessor = new ResultFrameTupleAccessor();
-                res.result = "";
-                while (reader.read(frame) > 0) {
-                    res.result += ResultUtils.getStringFromBuffer(frame.getBuffer(), frameTupleAccessor);
-                    frame.getBuffer().clear();
-                }
-                res.result.trim();
-                hcc.waitForCompletion(jobId);
-            } catch (HyracksException e) {
-                Throwable t = e;
-                while (t.getCause() != null) {
-                    t = t.getCause();
-                }
-                final String message = t.getMessage();
-                if (message != null) {
-                    Matcher m = EMBEDDED_SYSERROR_PATTERN.matcher(message);
-                    if (m.find()) {
-                        String eCode = m.group(1);
-                        throw new SystemException(ErrorCode.valueOf(eCode), e);
-                    }
+            QueryRequest request = createQueryRequest(opts, query);
+            APIResponse response = sendQueryRequest(request, testCase.getSourceFileMap());
+            if (response instanceof SyncQueryResponse) {
+                res.result = ((SyncQueryResponse) response).getResults();
+            } else {
+                System.err.println("Error response: Failure when running the query");
+                ErrorResponse errorResponse = (ErrorResponse) response;
+                Matcher m = EMBEDDED_SYSERROR_PATTERN.matcher(errorResponse.getError().getMessage());
+
+                Exception e = new RuntimeException("Failed to run the query");
+                if (m.find()) {
+                    String eCode = m.group(1);
+                    throw new SystemException(ErrorCode.valueOf(eCode), e);
+                } else {
+                    throw e;
                 }
-                throw e;
             }
         } catch (Throwable e) {
-            // Check for nested SystemExceptions.
-            Throwable error = e;
-            while (error != null) {
-                if (error instanceof SystemException) {
-                    res.error = error;
-                    break;
-                }
-                error = error.getCause();
-            }
-            // Default
-            if (res.error == null) {
-                res.error = e;
-            }
+            res.error = e;
         } finally {
             try {
                 res.compare();
@@ -208,6 +110,7 @@ public class TestRunner {
             long end = System.currentTimeMillis();
             res.time = end - start;
         }
+
         if (opts.showResult) {
             if (res.result == null) {
                 System.err.println("***Error: ");
@@ -218,7 +121,55 @@ public class TestRunner {
                 System.err.println(res.result);
             }
         }
+    }
+
+    private static QueryRequest createQueryRequest(XTestOptions opts, String query) {
+        QueryRequest request = new QueryRequest(query);
+        request.setCompileOnly(opts.compileOnly);
+        request.setOptimization(opts.optimizationLevel);
+        request.setFrameSize(opts.frameSize);
+        request.setShowAbstractSyntaxTree(opts.showAST);
+        request.setShowTranslatedExpressionTree(opts.showTET);
+        request.setShowOptimizedExpressionTree(opts.showOET);
+        request.setShowRuntimePlan(opts.showRP);
+        request.setAsync(false);
+
+        return request;
+    }
+
+    private static APIResponse sendQueryRequest(QueryRequest request, Map<String, File> sourceFileMap)
+            throws IOException, URISyntaxException {
+
+        URI uri = RestUtils.buildQueryURI(request, TestClusterUtil.localClusterUtil.getIpAddress(),
+                TestClusterUtil.localClusterUtil.getRestPort());
+        CloseableHttpClient httpClient = HttpClients.custom().build();
+
+        try {
+            HttpPost httpRequest = new HttpPost(uri);
+            httpRequest.setHeader(HttpHeaders.ACCEPT, CONTENT_TYPE_JSON);
+
+            ObjectMapper mapper = new ObjectMapper();
+            String fileMap = mapper.writeValueAsString(sourceFileMap);
+            httpRequest.setEntity(new StringEntity(fileMap, StandardCharsets.UTF_8));
+
+            try (CloseableHttpResponse httpResponse = httpClient.execute(httpRequest)) {
+                HttpEntity entity = httpResponse.getEntity();
+                String response = RestUtils.readEntity(entity);
+                if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
+                    return RestUtils.mapEntity(response, SyncQueryResponse.class, CONTENT_TYPE_JSON);
+                } else {
+                    return RestUtils.mapEntity(response, ErrorResponse.class, CONTENT_TYPE_JSON);
+                }
+            } catch (IOException e) {
+                System.err.println("Error occurred when reading entity: " + e.getMessage());
+            } catch (JAXBException e) {
+                System.err.println("Error occurred when mapping query response: " + e.getMessage());
+            }
+        } finally {
+            HttpClientUtils.closeQuietly(httpClient);
+        }
 
+        return null;
     }
 
     public void runQueries(TestCase testCase, TestCaseResult res) {

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java
----------------------------------------------------------------------
diff --git a/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java b/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java
index 5aae691..df7a71d 100644
--- a/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java
+++ b/vxquery-xtest/src/main/java/org/apache/vxquery/xtest/XTest.java
@@ -16,10 +16,6 @@
  */
 package org.apache.vxquery.xtest;
 
-import org.apache.hyracks.control.cc.ClusterControllerService;
-import org.apache.hyracks.control.nc.NodeControllerService;
-import org.mortbay.jetty.Server;
-
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -28,6 +24,8 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
+import org.mortbay.jetty.Server;
+
 public class XTest {
     private XTestOptions opts;
     private Server server;
@@ -36,8 +34,6 @@ public class XTest {
     private TestRunnerFactory trf;
     private int count;
     private int finishCount;
-    private static NodeControllerService nc;
-    private static ClusterControllerService cc;
 
     XTest(XTestOptions opts) {
         this.opts = opts;
@@ -81,8 +77,7 @@ public class XTest {
                 }
             }
         });
-        cc = TestClusterUtil.startCC(opts);
-        nc = TestClusterUtil.startNC();
+        TestClusterUtil.startCluster(opts, TestClusterUtil.localClusterUtil);
         trf = new TestRunnerFactory(opts);
         trf.registerReporters(reporters);
         TestCaseFactory tcf = new TestCaseFactory(trf, eSvc, opts);
@@ -104,7 +99,7 @@ public class XTest {
             r.close();
         }
         try {
-            TestClusterUtil.stopCluster(cc, nc);
+            TestClusterUtil.stopCluster(TestClusterUtil.localClusterUtil);
         } catch (IOException e) {
             e.printStackTrace();
         }

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-xtest/src/test/java/org/apache/vxquery/xtest/AbstractXQueryTest.java
----------------------------------------------------------------------
diff --git a/vxquery-xtest/src/test/java/org/apache/vxquery/xtest/AbstractXQueryTest.java b/vxquery-xtest/src/test/java/org/apache/vxquery/xtest/AbstractXQueryTest.java
index 1e2dcf6..8f77de4 100644
--- a/vxquery-xtest/src/test/java/org/apache/vxquery/xtest/AbstractXQueryTest.java
+++ b/vxquery-xtest/src/test/java/org/apache/vxquery/xtest/AbstractXQueryTest.java
@@ -22,8 +22,6 @@ import java.io.File;
 import java.io.IOException;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.hyracks.control.cc.ClusterControllerService;
-import org.apache.hyracks.control.nc.NodeControllerService;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -38,8 +36,6 @@ public abstract class AbstractXQueryTest {
     private TestRunner tr;
     private static MiniDFS dfs;
     private final static String TMP = "target/tmp";
-    private static NodeControllerService nc;
-    private static ClusterControllerService cc;
 
     protected abstract XTestOptions getTestOptions();
 
@@ -92,8 +88,7 @@ public abstract class AbstractXQueryTest {
 
     @BeforeClass
     public static void setup() throws IOException {
-        cc = TestClusterUtil.startCC(getDefaultTestOptions());
-        nc = TestClusterUtil.startNC();
+        TestClusterUtil.startCluster(getDefaultTestOptions(), TestClusterUtil.localClusterUtil);
         setupFS();
     }
 
@@ -116,7 +111,7 @@ public abstract class AbstractXQueryTest {
     @AfterClass
     public static void shutdown() throws IOException {
         removeFS();
-        TestClusterUtil.stopCluster(cc, nc);
+        TestClusterUtil.stopCluster(TestClusterUtil.localClusterUtil);
     }
 
     public static void removeFS() throws IOException {

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-1.txt
----------------------------------------------------------------------
diff --git a/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-1.txt b/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-1.txt
new file mode 100644
index 0000000..b1db973
--- /dev/null
+++ b/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-1.txt
@@ -0,0 +1,3 @@
+<value>33</value>
+<value>32</value>
+<value>31</value>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-2.txt
----------------------------------------------------------------------
diff --git a/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-2.txt b/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-2.txt
new file mode 100644
index 0000000..d93567e
--- /dev/null
+++ b/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-2.txt
@@ -0,0 +1,3 @@
+<value>33</value>
+<value>31</value>
+<value>32</value>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-3.txt
----------------------------------------------------------------------
diff --git a/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-3.txt b/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-3.txt
new file mode 100644
index 0000000..2ab8764
--- /dev/null
+++ b/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-3.txt
@@ -0,0 +1,3 @@
+<value>32</value>
+<value>33</value>
+<value>31</value>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/vxquery/blob/f2e5fd90/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-4.txt
----------------------------------------------------------------------
diff --git a/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-4.txt b/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-4.txt
new file mode 100644
index 0000000..d1d6bb7
--- /dev/null
+++ b/vxquery-xtest/src/test/resources/ExpectedTestResults/GhcndRecords/Partition-2/q03_records-4.txt
@@ -0,0 +1,3 @@
+<value>32</value>
+<value>31</value>
+<value>33</value>
\ No newline at end of file