changeset 144:b7f0912a6827

Update jvm-gc service with implementationts for PUT, POST and DELETE This patch implements PUT, POST and DELETE (GET is already implemented) for the jvm-gc service. The service is now fully functional and respects the API defined in jvm-gc-swagger.yaml. Mongo-related execution code has been moved to common/mongodb in the MongoExecutor class and is used by both the jvm-memory and jvm-gc services. Reviewed-by: ebaron Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-May/022974.html
author Jie Kang <jkang@redhat.com>
date Mon, 08 May 2017 10:30:02 -0400
parents b13937f1945f
children 3eca89ccecb1
files common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/executor/MongoExecutor.java common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilder.java common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilderTest.java services/jvm-gc/jvm-gc-swagger.json services/jvm-gc/jvm-gc-swagger.yaml services/jvm-gc/src/main/java/com/redhat/thermostat/service/jvm/gc/JvmGcHttpHandler.java services/jvm-gc/src/main/webapp/WEB-INF/web.xml services/jvm-memory/jvm-memory-swagger.yaml services/jvm-memory/src/main/java/com/redhat/thermostat/service/jvm/memory/JvmMemoryHttpHandler.java
diffstat 9 files changed, 309 insertions(+), 269 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/executor/MongoExecutor.java	Mon May 08 10:30:02 2017 -0400
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gateway.common.mongodb.executor;
+
+import static com.mongodb.client.model.Projections.excludeId;
+import static com.mongodb.client.model.Projections.fields;
+import static com.mongodb.client.model.Projections.include;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.bson.Document;
+import org.bson.conversions.Bson;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.CursorType;
+import com.mongodb.DBObject;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.util.JSON;
+import com.redhat.thermostat.gateway.common.mongodb.filters.MongoRequestFilters;
+import com.redhat.thermostat.gateway.common.mongodb.filters.MongoSortFilters;
+import com.redhat.thermostat.gateway.common.mongodb.response.MongoResponseBuilder;
+
+public class MongoExecutor {
+    private final MongoResponseBuilder mongoResponseBuilder = new MongoResponseBuilder();
+
+    public String buildGetResponse(MongoCollection<Document> collection, Integer limit, Integer offset, String sort, String queries, String projections) {
+        FindIterable<Document> documents;
+        if (queries != null) {
+            List<String> queriesList = Arrays.asList(queries.split(","));
+            final Bson query = MongoRequestFilters.buildQueriesFilter(queriesList);
+            documents = collection.find(query);
+        } else {
+            documents = collection.find();
+        }
+
+        List<String> projectionsList;
+        if (projections != null) {
+            projectionsList = Arrays.asList(projections.split(","));
+            documents = documents.projection(fields(include(projectionsList), excludeId()));
+        } else {
+            documents = documents.projection(excludeId());
+        }
+
+        final Bson sortObject = MongoSortFilters.createSortObject(sort);
+        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit).cursorType(CursorType.NonTailable);
+
+        return mongoResponseBuilder.buildGetResponseString(documents);
+    }
+
+
+    public void buildPutResponse(MongoCollection<Document> collection, String body, String queries) {
+        BasicDBObject inputObject = (BasicDBObject) JSON.parse(body);
+
+        final List<String> queriesList;
+        if (queries != null) {
+            queriesList = Arrays.asList(queries.split(","));
+        } else {
+            queriesList = Collections.emptyList();
+        }
+
+        BasicDBObject setObject = (BasicDBObject) inputObject.get("set");
+        final Bson fields = new Document("$set", setObject);
+
+        collection.updateMany(MongoRequestFilters.buildQueriesFilter(queriesList), fields);
+    }
+
+    public void buildDeleteResponse(MongoCollection<Document> collection, String queries) {
+        List<String> queriesList;
+        if (queries != null) {
+            queriesList = Arrays.asList(queries.split(","));
+            collection.deleteMany(MongoRequestFilters.buildQueriesFilter(queriesList));
+
+        } else {
+            collection.drop();
+        }
+    }
+
+    public void buildPost(MongoCollection<DBObject> collection, String body) {
+        if (body.length() > 0) {
+            List<DBObject> inputList = (List<DBObject>) JSON.parse(body);
+            collection.insertMany(inputList);
+        }
+    }
+}
--- a/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilder.java	Fri May 05 09:36:01 2017 -0400
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilder.java	Mon May 08 10:30:02 2017 -0400
@@ -60,7 +60,7 @@
      * }
      */
 
-    public static String buildGetResponse(FindIterable<Document> documents) {
+    public String buildGetResponseString(FindIterable<Document> documents) {
         final StringBuilder s = new StringBuilder();
 
         s.append("{ \"response\" : [");
@@ -83,4 +83,5 @@
 
         return s.toString();
     }
+
 }
--- a/common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilderTest.java	Fri May 05 09:36:01 2017 -0400
+++ b/common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilderTest.java	Mon May 08 10:30:02 2017 -0400
@@ -46,6 +46,7 @@
 
 import org.bson.Document;
 import org.bson.conversions.Bson;
+import org.junit.Before;
 import org.junit.Test;
 
 import com.mongodb.Block;
@@ -56,6 +57,14 @@
 import com.mongodb.client.MongoIterable;
 
 public class MongoResponseBuilderTest {
+
+    private MongoResponseBuilder mongoResponseBuilder;
+
+    @Before
+    public void setup() {
+        mongoResponseBuilder = new MongoResponseBuilder();
+    }
+
     @Test
     public void testBuildGetResponse() {
         Document d1 = Document.parse("{\"hello\" : \"blob\"}");
@@ -66,7 +75,7 @@
 
         FindIterable<Document> iterable = new TestFindIterable<>(list);
 
-        String output = MongoResponseBuilder.buildGetResponse(iterable);
+        String output = mongoResponseBuilder.buildGetResponseString(iterable);
         String expected = "{ \"response\" : [{ \"hello\" : \"blob\" },{ \"a\" : { \"blob\" : [\"hi\"] } }] }";
         assertEquals(expected, output);
     }
@@ -75,7 +84,7 @@
     public void testBuildEmptyGetResponse() {
         FindIterable<Document> iterable = new TestFindIterable<>(Collections.<Document>emptyList());
 
-        String output = MongoResponseBuilder.buildGetResponse(iterable);
+        String output = mongoResponseBuilder.buildGetResponseString(iterable);
         String expected = "{ \"response\" : [] }";
         assertEquals(expected, output);
     }
--- a/services/jvm-gc/jvm-gc-swagger.json	Fri May 05 09:36:01 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-{
-    "swagger": "2.0",
-    "info": {
-        "version": "0.0.1",
-        "title": "Thermostat Web Gateway JVM GC API",
-        "license": {
-            "name": "GPL v2 with Classpath Exception",
-            "url": "http://www.gnu.org/licenses"
-        }
-    },
-    "consumes": [
-        "application/json"
-    ],
-    "produces": [
-        "application/json",
-        "text/html; charset=utf-8"
-    ],
-    "basePath": "/0.0.1",
-    "paths": {
-        "/": {
-            "get": {
-                "description": "Get jvm gc information.",
-                "parameters": [
-                    {
-                        "$ref": "#/parameters/limit"
-                    },
-                    {
-                        "$ref": "#/parameters/offset"
-                    },
-                    {
-                        "$ref": "#/parameters/sort"
-                    },
-                    {
-                        "$ref": "#/parameters/projections"
-                    },
-                    {
-                        "$ref": "#/parameters/queries"
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK",
-                        "schema": {
-                            "$ref": "#/definitions/jvm-gc-stats"
-                        }
-                    }
-                }
-            },
-            "put": {
-                "description": "Create jvm gc information.",
-                "parameters": [
-                    {
-                        "$ref": "#/parameters/tags"
-                    },
-                    {
-                        "$ref": "#/parameters/jvm-gc-stats"
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK"
-                    }
-                }
-            },
-            "post": {
-                "description": "Update jvm gc information",
-                "parameters": [
-                    {
-                        "$ref": "#/parameters/tags"
-                    },
-                    {
-                        "$ref": "#/parameters/jvm-gc-stats"
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK"
-                    }
-                }
-            },
-            "delete": {
-                "description": "Delete jvm information.",
-                "parameters": [
-                    {
-                        "$ref": "#/parameters/queries"
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK"
-                    }
-                }
-            }
-        }
-    },
-    "definitions": {
-        "jvm-gc-stats": {
-            "type": "object"
-        }
-    },
-    "parameters": {
-        "jvm-gc-stats": {
-            "name": "jvm-gc-stats",
-            "in": "body",
-            "description": "The jvm gc statistics",
-            "required": true,
-            "schema": {
-                "$ref": "#/definitions/jvm-gc-stats"
-            }
-        },
-        "tags": {
-            "name": "t",
-            "in": "query",
-            "description": "CSV Tags string",
-            "type": "array",
-            "items": {
-                "type": "string"
-            }
-        },
-        "limit": {
-            "name": "l",
-            "in": "query",
-            "description": "Limit of items to return.",
-            "type": "integer",
-            "default": 100
-        },
-        "offset": {
-            "name": "o",
-            "in": "query",
-            "description": "Offset of items to return.",
-            "type": "integer",
-            "default": 0
-        },
-        "sort": {
-            "name": "s",
-            "in": "query",
-            "description": "CSV Sort string",
-            "type": "string"
-        },
-        "projections": {
-            "name": "p",
-            "in": "query",
-            "description": "Comma separated fields to filter the data",
-            "type": "string"
-        },
-        "queries": {
-            "name": "q",
-            "in": "query",
-            "description": "Comma separated Key, Comparator, Value trios to query the data",
-            "type": "string"
-        }
-    }
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/services/jvm-gc/jvm-gc-swagger.yaml	Mon May 08 10:30:02 2017 -0400
@@ -0,0 +1,123 @@
+swagger: '2.0'
+info:
+  version: 0.0.2
+  title: Thermostat Web Gateway JVM GC API
+  license:
+    name: GPL v2 with Classpath Exception
+    url: 'http://www.gnu.org/licenses'
+consumes:
+  - application/json
+produces:
+  - application/json
+  - text/html; charset=utf-8
+basePath: /0.0.2
+paths:
+  /:
+    get:
+      description: Get jvm gc information.
+      parameters:
+        - $ref: '#/parameters/limit'
+        - $ref: '#/parameters/offset'
+        - $ref: '#/parameters/sort'
+        - $ref: '#/parameters/projection'
+        - $ref: '#/parameters/query'
+      responses:
+        '200':
+          description: OK
+          schema:
+            $ref: '#/definitions/jvm-gc-stats-response'
+    put:
+      description: Update jvm gc information.
+      parameters:
+        - $ref: '#/parameters/put-body'
+        - $ref: '#/parameters/query'
+      responses:
+        '200':
+          description: OK
+    post:
+      description: Add jvm gc information
+      parameters:
+        - $ref: '#/parameters/jvm-gc-stats'
+      responses:
+        '200':
+          description: OK
+    delete:
+      description: Delete jvm gc information.
+      parameters:
+        - $ref: '#/parameters/query'
+      responses:
+        '200':
+          description: OK
+definitions:
+  jvm-gc-stats-response:
+    type: object
+    properties:
+      response:
+          $ref: '#/definitions/jvm-gc-stats'
+  jvm-gc-stats:
+    type: array
+    items:
+      $ref: '#/definitions/jvm-gc-stat'
+  jvm-gc-stat:
+    type: object
+    properties:
+      agentId:
+        type: string
+      jvmId:
+        type: string
+      timeStamp:
+        type: integer
+        format: int64
+      collectorName:
+        type: string
+      runCount:
+        type: integer
+        format: int64
+      wallTime:
+        type: integer
+        format: int64
+  put-body:
+    type: object
+    properties:
+      "set":
+        type: object
+parameters:
+  jvm-gc-stats:
+    name: jvm-gc-stats
+    in: body
+    description: The jvm gc statistics
+    required: true
+    schema:
+      $ref: '#/definitions/jvm-gc-stats'
+  put-body:
+    name: putBody
+    in: body
+    description: "The JSON object containing a 'set' object. This contains single item JSON objects that specify the field to replace and the JSON value to replace with. Example { \"set\" : { \"field\" : \"value\", \"field2\":{\"object\":\"item\"} }"
+    required: true
+    schema:
+      $ref: '#/definitions/put-body'
+  limit:
+    name: l
+    in: query
+    description: Limit of items to return. Example '1'
+    type: integer
+  offset:
+    name: o
+    in: query
+    description: Offset of items to return. Example '0'
+    type: integer
+  sort:
+    name: s
+    in: query
+    description: Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?s=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.
+    type: string
+  query:
+    name: q
+    in: query
+    description: Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?q=a==b,c!=d'. Keys are fields in documents and use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.
+    type: string
+  projection:
+    name: p
+    in: query
+    description: Projection string. Comma separated list of fields to include in the response. Example '?p=a,b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.
+    type: string
\ No newline at end of file
--- a/services/jvm-gc/src/main/java/com/redhat/thermostat/service/jvm/gc/JvmGcHttpHandler.java	Fri May 05 09:36:01 2017 -0400
+++ b/services/jvm-gc/src/main/java/com/redhat/thermostat/service/jvm/gc/JvmGcHttpHandler.java	Mon May 08 10:30:02 2017 -0400
@@ -36,14 +36,6 @@
 
 package com.redhat.thermostat.service.jvm.gc;
 
-import static com.mongodb.client.model.Projections.excludeId;
-import static com.mongodb.client.model.Projections.fields;
-import static com.mongodb.client.model.Projections.include;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 import javax.servlet.ServletContext;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -57,78 +49,83 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
-import org.bson.Document;
-import org.bson.conversions.Bson;
 
-import com.mongodb.CursorType;
-import com.mongodb.client.FindIterable;
+import com.mongodb.DBObject;
 import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
-import com.redhat.thermostat.gateway.common.mongodb.filters.MongoRequestFilters;
-import com.redhat.thermostat.gateway.common.mongodb.filters.MongoSortFilters;
-import com.redhat.thermostat.gateway.common.mongodb.response.MongoResponseBuilder;
+import com.redhat.thermostat.gateway.common.mongodb.executor.MongoExecutor;
 import com.redhat.thermostat.gateway.common.mongodb.servlet.ServletContextConstants;
 
 @Path("/")
 public class JvmGcHttpHandler {
-    private final String collectionName = "vm-gc-stats";
+    private final MongoExecutor mongoExecutor = new MongoExecutor();
+    private final String collectionName = "jvm-gc";
 
     @GET
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response getJvmMemory(@QueryParam("l") @DefaultValue("1") Integer limit,
-                                 @QueryParam("o") @DefaultValue("1") Integer offset,
+                                 @QueryParam("o") @DefaultValue("0") Integer offset,
                                  @QueryParam("s") String sort,
                                  @QueryParam("q") String queries,
                                  @QueryParam("p") String projections,
                                  @Context ServletContext context
     ) {
-        List<String> queriesList;
-        if (queries != null) {
-            queriesList = Arrays.asList(queries.split(","));
-        } else {
-            queriesList = Collections.emptyList();
-        }
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
 
-        List<String> projectionsList;
-        if (projections != null) {
-            projectionsList = Arrays.asList(projections.split(","));
-        } else {
-            projectionsList = Collections.emptyList();
-        }
+            String message = mongoExecutor.buildGetResponse(storage.getDatabase().getCollection(collectionName), limit, offset, sort, queries, projections);
 
-        final Bson query = MongoRequestFilters.buildQueriesFilter(queriesList);
-
-        final Bson sortObject = MongoSortFilters.createSortObject(sort);
-
-        ThermostatMongoStorage storage;
-        synchronized (context) {
-            storage = (ThermostatMongoStorage)context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            return Response.status(Response.Status.OK).entity(message).build();
+        } catch (Exception e) {
+            return Response.status(Response.Status.BAD_REQUEST).build();
         }
-        FindIterable<Document> documents = storage.getDatabase().getCollection(collectionName).find(query).projection(fields(include(projectionsList), excludeId())).sort(sortObject).limit(limit).skip(offset).batchSize(limit).cursorType(CursorType.NonTailable);
-
-        String message = MongoResponseBuilder.buildGetResponse(documents);
-
-        return Response.status(Response.Status.OK).entity(message).build();
     }
 
     @PUT
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response putJvmMemory() {
-        return Response.ok().build();
+    public Response putJvmMemory(String body,
+                                 @QueryParam("q") String queries,
+                                 @Context ServletContext context) {
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+
+            mongoExecutor.buildPutResponse(storage.getDatabase().getCollection(collectionName), body, queries);
+
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return Response.status(Response.Status.BAD_REQUEST).build();
+        }
     }
 
     @POST
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response postJvmMemory() {
-        return Response.ok().build();
+    public Response postJvmMemory(String body,
+                                  @Context ServletContext context) {
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+
+            mongoExecutor.buildPost(storage.getDatabase().getCollection(collectionName, DBObject.class), body);
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return Response.status(Response.Status.BAD_REQUEST).build();
+        }
     }
 
     @DELETE
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response deleteJvmMemory() {
-        return Response.ok().build();
+    public Response deleteJvmMemory(@QueryParam("q") String queries,
+                                    @Context ServletContext context) {
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+
+            mongoExecutor.buildDeleteResponse(storage.getDatabase().getCollection(collectionName), queries);
+
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return Response.status(Response.Status.BAD_REQUEST).build();
+        }
     }
 }
--- a/services/jvm-gc/src/main/webapp/WEB-INF/web.xml	Fri May 05 09:36:01 2017 -0400
+++ b/services/jvm-gc/src/main/webapp/WEB-INF/web.xml	Mon May 08 10:30:02 2017 -0400
@@ -54,7 +54,7 @@
     </servlet>
     <servlet-mapping>
         <servlet-name>JvmGcServlet</servlet-name>
-        <url-pattern>/0.0.1/*</url-pattern>
+        <url-pattern>/0.0.2/*</url-pattern>
     </servlet-mapping>
     <!-- Service configuration -->
     <context-param>
--- a/services/jvm-memory/jvm-memory-swagger.yaml	Fri May 05 09:36:01 2017 -0400
+++ b/services/jvm-memory/jvm-memory-swagger.yaml	Mon May 08 10:30:02 2017 -0400
@@ -10,7 +10,7 @@
 produces:
   - application/json
   - text/html; charset=utf-8
-basePath: /0.0.1
+basePath: /0.0.2
 paths:
   /:
     get:
--- a/services/jvm-memory/src/main/java/com/redhat/thermostat/service/jvm/memory/JvmMemoryHttpHandler.java	Fri May 05 09:36:01 2017 -0400
+++ b/services/jvm-memory/src/main/java/com/redhat/thermostat/service/jvm/memory/JvmMemoryHttpHandler.java	Mon May 08 10:30:02 2017 -0400
@@ -36,14 +36,6 @@
 
 package com.redhat.thermostat.service.jvm.memory;
 
-import static com.mongodb.client.model.Projections.excludeId;
-import static com.mongodb.client.model.Projections.fields;
-import static com.mongodb.client.model.Projections.include;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 import javax.servlet.ServletContext;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -57,23 +49,15 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
-import org.bson.Document;
-import org.bson.conversions.Bson;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.CursorType;
 import com.mongodb.DBObject;
-import com.mongodb.client.FindIterable;
-import com.mongodb.util.JSON;
 import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
-import com.redhat.thermostat.gateway.common.mongodb.filters.MongoRequestFilters;
-import com.redhat.thermostat.gateway.common.mongodb.filters.MongoSortFilters;
-import com.redhat.thermostat.gateway.common.mongodb.response.MongoResponseBuilder;
+import com.redhat.thermostat.gateway.common.mongodb.executor.MongoExecutor;
 import com.redhat.thermostat.gateway.common.mongodb.servlet.ServletContextConstants;
 
 @Path("/")
 public class JvmMemoryHttpHandler {
 
+    private final MongoExecutor mongoExecutor = new MongoExecutor();
     private final String collectionName = "jvm-memory";
 
     @GET
@@ -89,28 +73,7 @@
         try {
             ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
 
-            FindIterable<Document> documents;
-            if (queries != null) {
-                List<String> queriesList = Arrays.asList(queries.split(","));
-                final Bson query = MongoRequestFilters.buildQueriesFilter(queriesList);
-                documents = storage.getDatabase().getCollection(collectionName).find(query);
-            } else {
-                documents = storage.getDatabase().getCollection(collectionName).find();
-            }
-
-
-            List<String> projectionsList;
-            if (projections != null) {
-                projectionsList = Arrays.asList(projections.split(","));
-                documents = documents.projection(fields(include(projectionsList), excludeId()));
-            } else {
-                documents = documents.projection(excludeId());
-            }
-
-            final Bson sortObject = MongoSortFilters.createSortObject(sort);
-            documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit).cursorType(CursorType.NonTailable);
-
-            String message = MongoResponseBuilder.buildGetResponse(documents);
+            String message = mongoExecutor.buildGetResponse(storage.getDatabase().getCollection(collectionName), limit, offset, sort, queries, projections);
 
             return Response.status(Response.Status.OK).entity(message).build();
         } catch (Exception e) {
@@ -127,19 +90,8 @@
         try {
             ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
 
-            BasicDBObject inputObject = (BasicDBObject) JSON.parse(body);
+            mongoExecutor.buildPutResponse(storage.getDatabase().getCollection(collectionName), body, queries);
 
-            final List<String> queriesList;
-            if (queries != null) {
-                queriesList = Arrays.asList(queries.split(","));
-            } else {
-                queriesList = Collections.emptyList();
-            }
-
-            BasicDBObject setObject = (BasicDBObject) inputObject.get("set");
-            final Bson fields = new Document("$set", setObject);
-
-            storage.getDatabase().getCollection(collectionName).updateMany(MongoRequestFilters.buildQueriesFilter(queriesList), fields);
             return Response.status(Response.Status.OK).build();
         } catch (Exception e) {
             return Response.status(Response.Status.BAD_REQUEST).build();
@@ -154,10 +106,7 @@
         try {
             ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
 
-            if (body.length() > 0) {
-                List<DBObject> inputList = (List<DBObject>) JSON.parse(body);
-                storage.getDatabase().getCollection(collectionName, DBObject.class).insertMany(inputList);
-            }
+            mongoExecutor.buildPost(storage.getDatabase().getCollection(collectionName, DBObject.class), body);
             return Response.status(Response.Status.OK).build();
         } catch (Exception e) {
             return Response.status(Response.Status.BAD_REQUEST).build();
@@ -172,14 +121,7 @@
         try {
             ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
 
-            List<String> queriesList;
-            if (queries != null) {
-                queriesList = Arrays.asList(queries.split(","));
-                storage.getDatabase().getCollection(collectionName).deleteMany(MongoRequestFilters.buildQueriesFilter(queriesList));
-
-            } else {
-                storage.getDatabase().getCollection(collectionName).drop();
-            }
+            mongoExecutor.buildDeleteResponse(storage.getDatabase().getCollection(collectionName), queries);
 
             return Response.status(Response.Status.OK).build();
         } catch (Exception e) {