changeset 208:d986807bc783

Unify common web service service code (part 1) This huge patch starts down the road to unify all the web service common code. This patch moves all potentially common code to one helper class. Unfortunately, currently some services MongoExecutor and some use MongoStorageHandler under the hood - this doesn't fix that yet. Some services support realms, some don't. Again, not fixed yet. Some services support pagination, or metadata ...(etc). All that will be in subsequent patches, but all the code to fix is now in one place only. Some behaviours are changed: the 'projection' parameter has completely vanished from any service that supported it (replaced with 'include'/'exclude'), and all service use the long forms of their parameter names; i.e.'query' instead of 'q' (this is now defined in ONE place instead of hard coded in 16!). There will need to be some changes to the web-client to support the new parameter formats (if any are actually used). Reviewed-by: sgehwolf Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-July/024029.html Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-July/024240.html
author Simon Tooke <stooke@redhat.com>
date Fri, 21 Jul 2017 09:30:27 -0400
parents 77039945b1ad
children aeb1467ddd67
files common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/MongoStorageHandler.java common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/ThermostatFields.java 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/filters/MongoQuery.java common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/filters/MongoRequestFilters.java common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoMetaDataGenerator.java common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoMetaDataResponseBuilder.java common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilder.java common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/servlet/MongoHttpHandlerHelper.java common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/servlet/RequestParameters.java common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoMetaDataGeneratorTest.java common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilderTest.java services/jvm-gc/src/main/java/com/redhat/thermostat/service/jvm/gc/JvmGcHttpHandler.java services/jvm-gc/src/main/resources/jvm-gc-swagger.yaml services/jvm-memory/src/main/java/com/redhat/thermostat/service/jvm/memory/JvmMemoryHttpHandler.java services/jvm-memory/src/main/resources/jvm-memory-swagger.yaml services/jvms/src/main/java/com/redhat/thermostat/service/jvms/http/JvmsHttpHandler.java services/jvms/src/main/java/com/redhat/thermostat/service/jvms/http/Parameters.java services/jvms/src/main/java/com/redhat/thermostat/service/jvms/mongo/Fields.java services/jvms/src/main/java/com/redhat/thermostat/service/jvms/mongo/JvmInfoMongoStorageHandler.java services/jvms/src/main/java/com/redhat/thermostat/service/jvms/mongo/MongoStorageHandler.java services/jvms/src/main/java/com/redhat/thermostat/service/jvms/mongo/StorageFields.java services/system-cpu/src/main/java/com/redhat/thermostat/service/system/cpu/http/Parameters.java services/system-cpu/src/main/java/com/redhat/thermostat/service/system/cpu/http/SystemInfoCPUHttpHandler.java services/system-cpu/src/main/java/com/redhat/thermostat/service/system/cpu/mongo/Fields.java services/system-cpu/src/main/java/com/redhat/thermostat/service/system/cpu/mongo/MongoStorageHandler.java services/system-memory/src/main/java/com/redhat/thermostat/service/system/memory/http/Parameters.java services/system-memory/src/main/java/com/redhat/thermostat/service/system/memory/http/SystemMemoryHttpHandler.java services/system-memory/src/main/java/com/redhat/thermostat/service/system/memory/mongo/Fields.java services/system-memory/src/main/java/com/redhat/thermostat/service/system/memory/mongo/MongoStorageHandler.java services/system-memory/src/main/resources/memory-info-swagger.yaml services/system-memory/src/main/resources/system-memory-swagger.yaml services/system-network/src/main/java/com/redhat/thermostat/service/system/network/http/Parameters.java services/system-network/src/main/java/com/redhat/thermostat/service/system/network/http/SystemNetworkHttpHandler.java services/system-network/src/main/java/com/redhat/thermostat/service/system/network/mongo/Fields.java services/system-network/src/main/java/com/redhat/thermostat/service/system/network/mongo/MongoStorageHandler.java services/systems/src/main/java/com/redhat/thermostat/service/systems/http/Parameters.java services/systems/src/main/java/com/redhat/thermostat/service/systems/http/SystemsHttpHandler.java services/systems/src/main/java/com/redhat/thermostat/service/systems/mongo/Fields.java services/systems/src/main/java/com/redhat/thermostat/service/systems/mongo/MongoStorageHandler.java tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/gc/JvmGcServiceIntegrationTest.java tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/memory/JvmMemoryServiceIntegrationTest.java tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvms/JvmsServiceIntegrationTest.java tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/system/network/SystemNetworkIntegrationTest.java
diffstat 44 files changed, 1512 insertions(+), 2177 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/MongoStorageHandler.java	Fri Jul 21 09:30:27 2017 -0400
@@ -0,0 +1,157 @@
+/*
+ * 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;
+
+import static com.mongodb.client.model.Filters.and;
+import static com.mongodb.client.model.Filters.eq;
+import static com.mongodb.client.model.Projections.exclude;
+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 static com.redhat.thermostat.gateway.common.mongodb.filters.MongoRequestFilters.buildAnd;
+import static com.redhat.thermostat.gateway.common.mongodb.filters.MongoRequestFilters.buildEq;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.redhat.thermostat.gateway.common.mongodb.filters.MongoQuery;
+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 MongoStorageHandler {
+
+    private static final String SET_FIELD_NAME = "set";
+
+    private final MongoResponseBuilder.Builder mongoResponseBuilder = new MongoResponseBuilder.Builder();
+
+    public String getMany(MongoCollection<Document> collection, String queries, Integer limit, Integer offset, String sort, String includes, String excludes) {
+        final MongoQuery query = queries == null ? null : new MongoQuery(MongoRequestFilters.buildQueriesFilter(queries));
+        return getMany(collection, query, limit, offset, sort, includes, excludes);
+    }
+
+    public String getMany(MongoCollection<Document> collection, Bson query, Integer limit, Integer offset, String sort, String includes, String excludes) {
+        FindIterable<Document> documents = query == null ? collection.find() : collection.find(query);
+        documents = buildProjection(documents, includes, excludes);
+        final Bson sortObject = MongoSortFilters.createSortObject(sort);
+        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit).cursorType(CursorType.NonTailable);
+        return mongoResponseBuilder.addQueryDocuments(documents).build();
+    }
+
+    private FindIterable<Document> buildProjection(FindIterable<Document> documents, String includes, String excludes) {
+        if (excludes != null) {
+            List<String> excludesList = Arrays.asList(excludes.split(","));
+            documents = documents.projection(fields(exclude(excludesList), excludeId()));
+        } else if (includes != null) {
+            List<String> includesList = Arrays.asList(includes.split(","));
+            documents = documents.projection(fields(include(includesList), excludeId()));
+        } else {
+            documents = documents.projection(excludeId());
+        }
+
+        return documents;
+    }
+
+    public void addSystemObjects(MongoCollection<DBObject> collection, String systemId, String body) {
+        if (body.length() > 0) {
+            List<DBObject> inputList = (List<DBObject>) JSON.parse(body);
+            for (DBObject o : inputList) {
+                o.put(ThermostatFields.SYSTEM_ID, systemId);
+            }
+            collection.insertMany(inputList);
+        }
+    }
+
+    public void addJvmObjects(MongoCollection<DBObject> collection, String systemId, String jvmId, String body) {
+        if (body.length() > 0) {
+            List<DBObject> inputList = (List<DBObject>) JSON.parse(body);
+            for (DBObject o : inputList) {
+                o.put(ThermostatFields.SYSTEM_ID, systemId);
+                o.put(ThermostatFields.JVM_ID, jvmId);
+            }
+            collection.insertMany(inputList);
+        }
+    }
+
+    public void deleteMany(MongoCollection<Document> collection, Bson query) {
+        collection.deleteMany(query);
+    }
+
+    public void updateOneSystemObject(MongoCollection<Document> collection, final String systemId, String queries, String body) {
+        Bson sysQuery = buildEq(ThermostatFields.SYSTEM_ID, systemId);
+        Bson query  = buildAnd(sysQuery, MongoRequestFilters.buildQueriesFilter(queries));
+
+        BasicDBObject inputObject = (BasicDBObject) JSON.parse(body);
+        BasicDBObject setObject = (BasicDBObject) inputObject.get(SET_FIELD_NAME);
+
+        if (setObject.containsField(ThermostatFields.SYSTEM_ID)) {
+            throw new UnsupportedOperationException("Updating " + ThermostatFields.SYSTEM_ID + " field is not allowed");
+        }
+
+        final Bson fields = new Document("$set", setObject);
+
+        collection.updateMany(query, fields);
+    }
+
+    public void updateOneJvmObject(MongoCollection<Document> collection, final String systemId, final String jvmId, String queries, String body) {
+        Bson sysQuery = buildEq(ThermostatFields.SYSTEM_ID, systemId);
+        Bson jvmQuery = buildEq(ThermostatFields.JVM_ID, jvmId);
+        Bson query  = buildAnd(buildAnd(sysQuery, jvmQuery), MongoRequestFilters.buildQueriesFilter(queries));
+
+        BasicDBObject inputObject = (BasicDBObject) JSON.parse(body);
+        BasicDBObject setObject = (BasicDBObject) inputObject.get(SET_FIELD_NAME);
+
+        if (setObject.containsField(ThermostatFields.SYSTEM_ID)) {
+            throw new UnsupportedOperationException("Updating " + ThermostatFields.SYSTEM_ID + " field is not allowed");
+        }
+        if (setObject.containsField(ThermostatFields.JVM_ID)) {
+            throw new UnsupportedOperationException("Updating " + ThermostatFields.JVM_ID + " field is not allowed");
+        }
+        final Bson fields = new Document("$set", setObject);
+
+        collection.updateMany(query, fields);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/ThermostatFields.java	Fri Jul 21 09:30:27 2017 -0400
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+public interface ThermostatFields {
+    String SYSTEM_ID = "systemId";
+    String JVM_ID = "jvmId";
+    String TIMESTAMP = "timeStamp";
+}
--- a/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/executor/MongoExecutor.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/executor/MongoExecutor.java	Fri Jul 21 09:30:27 2017 -0400
@@ -36,6 +36,7 @@
 
 package com.redhat.thermostat.gateway.common.mongodb.executor;
 
+import static com.mongodb.client.model.Projections.exclude;
 import static com.mongodb.client.model.Projections.excludeId;
 import static com.mongodb.client.model.Projections.fields;
 import static com.mongodb.client.model.Projections.include;
@@ -46,6 +47,7 @@
 import java.util.List;
 import java.util.Set;
 
+import com.redhat.thermostat.gateway.common.mongodb.MongoStorageHandler;
 import org.bson.Document;
 import org.bson.conversions.Bson;
 
@@ -60,31 +62,23 @@
 
 public class MongoExecutor {
     public MongoDataResultContainer execGetRequest(MongoCollection<Document> collection, Integer limit, Integer offset,
-                                                   String sort, String queries, String projections,
+                                                   String sort, String queries, String includes, String excludes,
                                                    Set<String> realms) throws IOException {
-        return execGetRequest(collection, limit, offset, sort, buildClientQueries(queries), projections, realms);
+        return execGetRequest(collection, limit, offset, sort, buildClientQueries(queries), includes, excludes, realms);
     }
 
     public MongoDataResultContainer execGetRequest(MongoCollection<Document> collection, Integer limit, Integer offset,
-                                                   String sort, List<String> queries, String projections,
+                                                   String sort, List<String> queries, String includes, String excludes,
                                                    Set<String> realms) {
         FindIterable<Document> documents = collection.find();
         MongoDataResultContainer queryDataContainer = new MongoDataResultContainer();
 
         Bson query = MongoRequestFilters.buildQuery(queries, realms);
         documents = documents.filter(query);
-
         long count = collection.count(query);
         queryDataContainer.setGetReqCount(count);
         queryDataContainer.setRemainingNumQueryDocuments((int) (count - (limit + offset)));
-
-        if (projections != null) {
-            List<String> projectionsList = Arrays.asList(projections.split(","));
-            documents = documents.projection(fields(include(projectionsList), excludeId()));
-        } else {
-            documents = documents.projection(excludeId());
-        }
-
+        documents = buildProjection(documents, includes, excludes);
         final Bson sortObject = MongoSortFilters.createSortObject(sort);
         documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit).cursorType(CursorType.NonTailable);
         queryDataContainer.setQueryDataResult(documents);
@@ -157,7 +151,6 @@
         return metaDataContainer;
     }
 
-
     private List<String> buildClientQueries(String queries) throws IOException {
         if (queries != null) {
             List<String> queriesList = Arrays.asList(queries.split(","));
@@ -172,4 +165,18 @@
             return Collections.emptyList();
         }
     }
+
+    public static FindIterable<Document> buildProjection(FindIterable<Document> documents, String includes, String excludes) {
+        if (excludes != null) {
+            List<String> excludesList = Arrays.asList(excludes.split(","));
+            documents = documents.projection(fields(exclude(excludesList), excludeId()));
+        } else if (includes != null) {
+            List<String> includesList = Arrays.asList(includes.split(","));
+            documents = documents.projection(fields(include(includesList), excludeId()));
+        } else {
+            documents = documents.projection(excludeId());
+        }
+
+        return documents;
+    }
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/filters/MongoQuery.java	Fri Jul 21 09:30:27 2017 -0400
@@ -0,0 +1,55 @@
+/*
+ * 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.filters;
+
+import org.bson.BsonDocument;
+import org.bson.codecs.configuration.CodecRegistry;
+import org.bson.conversions.Bson;
+
+public class MongoQuery implements Bson {
+
+    private final Bson bson;
+
+    public MongoQuery(Bson bson) {
+        this.bson = bson;
+    }
+
+    @Override
+    public <TDocument> BsonDocument toBsonDocument(Class<TDocument> aClass, CodecRegistry codecRegistry) {
+        return bson.toBsonDocument(aClass, codecRegistry);
+    }
+}
--- a/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/filters/MongoRequestFilters.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/filters/MongoRequestFilters.java	Fri Jul 21 09:30:27 2017 -0400
@@ -45,8 +45,11 @@
 import static com.mongodb.client.model.Filters.lte;
 import static com.mongodb.client.model.Filters.ne;
 import static com.mongodb.client.model.Filters.size;
+import static com.mongodb.client.model.Filters.or;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import java.util.regex.Matcher;
@@ -59,11 +62,25 @@
 import com.redhat.thermostat.gateway.common.mongodb.keycloak.KeycloakFields;
 
 public class MongoRequestFilters {
-    public static Bson buildQueriesFilter(List<String> queries) {
-        List<Bson> filters = new ArrayList<>();
+
+    private static final Pattern operatorPattern = Pattern.compile("(<=|>=|<|>|==|!=)");
+
+    public static Bson buildEq(final String key, final String value) {
+        return eq(key, value);
+    }
+
+    public static Bson buildAnd(final Bson a1, final Bson a2) {
+        return and(a1, a2);
+    }
+
+    public static Bson buildOr(final Bson a1, final Bson a2) {
+        return or(a1, a2);
+    }
+
+    public static List<Bson> buildQueriesList(List<String> queries) {
+        final List<Bson> filters = new ArrayList<>();
         for (String filter : queries) {
-            Pattern p = Pattern.compile("(<=|>=|<|>|==|!=)");
-            Matcher m = p.matcher(filter);
+            final Matcher m = operatorPattern.matcher(filter);
             if (m.find()) {
                 String key = filter.substring(0, m.start());
                 String comparator = filter.substring(m.start(), m.end());
@@ -105,7 +122,25 @@
                 throw new JsonParseException("No relation found in: " + filter);
             }
         }
-        return and(filters);
+        return filters;
+    }
+
+    public static List<Bson> buildQueriesList(final String queryStr) {
+        if (queryStr == null || queryStr.isEmpty()) {
+            return Collections.EMPTY_LIST;
+        } else {
+            final List<String> queries = Arrays.asList(queryStr.split(","));
+            final List<Bson> filters = buildQueriesList(queries);
+            return filters;
+        }
+    }
+
+    public static Bson buildQueriesFilter(final List<String> queries) {
+        return and(buildQueriesList(queries));
+    }
+
+    public static Bson buildQueriesFilter(final String queryStr) {
+        return and(buildQueriesList(queryStr));
     }
 
     public static Bson buildRealmsFilter(Set<String> realms) {
--- a/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoMetaDataGenerator.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoMetaDataGenerator.java	Fri Jul 21 09:30:27 2017 -0400
@@ -38,6 +38,7 @@
 
 import javax.servlet.http.HttpServletRequest;
 
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
 import com.redhat.thermostat.gateway.common.mongodb.executor.MongoDataResultContainer;
 
 public class MongoMetaDataGenerator {
@@ -46,18 +47,20 @@
     private final Integer offset;
     private final String sort;
     private final String queries;
-    private final String projections;
+    private final String includes;
+    private final String excludes;
     private final MongoDataResultContainer execResult;
     private final HttpServletRequest requestInfo;
     private final String baseURL;
 
-    public MongoMetaDataGenerator(Integer limit, Integer offset, String sort, String queries, String projections,
+    public MongoMetaDataGenerator(Integer limit, Integer offset, String sort, String queries, String includes, String excludes,
                                   HttpServletRequest requestInfo, MongoDataResultContainer execResult) {
         this.limit = limit;
         this.offset = offset;
         this.sort = sort;
         this.queries = queries;
-        this.projections = projections;
+        this.includes = includes;
+        this.excludes = excludes;
         this.execResult = execResult;
         this.requestInfo = requestInfo;
         this.baseURL = requestInfo.getRequestURL().toString();
@@ -80,9 +83,9 @@
             if (limit > 1) {
                 int newLim = (offset >= limit) ? limit : offset;
                 int newOff = (offset >= limit) ? (offset - limit) : 0;
-                prev.append("&").append("l=").append(newLim).append("&").append("o=").append(newOff);
+                prev.append("&").append(RequestParameters.LIMIT + '=').append(newLim).append("&").append(RequestParameters.OFFSET + '=').append(newOff);
             } else {
-                prev.append("&").append("l=").append(offset);
+                prev.append("&").append(RequestParameters.LIMIT + '=').append(offset);
             }
 
             response.prev(prev.toString());
@@ -95,7 +98,7 @@
             if (!limit.equals(0) && remaining != 0) {
                 StringBuilder next = new StringBuilder();
                 int nextLimit = (remaining > limit) ? limit : remaining;
-                next.append(baseURL).append("?o=").append(offset + limit).append("&l=").append(nextLimit).append("&");
+                next.append(baseURL).append('?' + RequestParameters.OFFSET + '=').append(offset + limit).append('&' + RequestParameters.LIMIT + '=').append(nextLimit).append("&");
 
                 String[] arguments = requestInfo.getQueryString().split("&");
                 next.append(response.getQueryArgumentsNoOffsetLimit(arguments));
--- a/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoMetaDataResponseBuilder.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoMetaDataResponseBuilder.java	Fri Jul 21 09:30:27 2017 -0400
@@ -38,6 +38,7 @@
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
 
 /*
  *  Builds the appropriate metadata for the response after executing the request's MongoDB Query.
@@ -123,7 +124,7 @@
             StringBuilder queryString = new StringBuilder();
             String sep = "";
             for (String arg : URLQueryPath) {
-                if (!(arg.contains("limit") || arg.contains("offset") || arg.contains("o") || arg.contains("l"))) {
+                if (!(arg.contains(RequestParameters.LIMIT) || arg.contains(RequestParameters.OFFSET))) {
                     queryString.append(sep).append(arg);
                     sep = "&";
                 }
--- a/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilder.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilder.java	Fri Jul 21 09:30:27 2017 -0400
@@ -38,6 +38,7 @@
 
 import java.util.ArrayList;
 
+import com.redhat.thermostat.gateway.common.mongodb.executor.MongoDataResultContainer;
 import org.bson.Document;
 
 import com.google.gson.Gson;
@@ -46,6 +47,8 @@
 import com.mongodb.client.FindIterable;
 import com.redhat.thermostat.gateway.common.mongodb.keycloak.KeycloakFields;
 
+import javax.servlet.http.HttpServletRequest;
+
 /*
  *  Builds the appropriate response after executing the request's MongoDB Query.
  *
@@ -63,7 +66,7 @@
         private MongoMetaDataResponseBuilder metaData;
         private final Gson gson = new GsonBuilder().create();
 
-        public Builder queryDocuments(FindIterable<Document> documents) {
+        public Builder addQueryDocuments(FindIterable<Document> documents) {
             queryDocuments = new ArrayList<>();
             documents.forEach(new Block<Document>() {
                 @Override
@@ -77,7 +80,7 @@
             return this;
         }
 
-        public Builder metaData(MongoMetaDataResponseBuilder metaData) {
+        public Builder addMetaData(MongoMetaDataResponseBuilder metaData) {
             this.metaData = metaData;
             return this;
         }
@@ -88,6 +91,24 @@
         }
     }
 
+    public static String build(final MongoDataResultContainer execResult) {
+        final MongoResponseBuilder.Builder response = new MongoResponseBuilder.Builder();
+        response.addQueryDocuments(execResult.getQueryDataResult());
+        return response.build();
+    }
+
+    public static String buildWithMetadata(final MongoDataResultContainer execResult, int limit, int offset, String sort, String queries, String includes, String excludes, HttpServletRequest requestInfo) {
+        final MongoResponseBuilder.Builder response = new MongoResponseBuilder.Builder();
+        response.addQueryDocuments(execResult.getQueryDataResult());
+        final MongoMetaDataResponseBuilder.MetaBuilder metaDataResponse = new MongoMetaDataResponseBuilder.MetaBuilder();
+        final MongoMetaDataGenerator metaDataGenerator = new MongoMetaDataGenerator(limit, offset, sort, queries, includes, excludes, requestInfo, execResult);
+        metaDataGenerator.setDocAndPayloadCount(metaDataResponse);
+        metaDataGenerator.setPrev(metaDataResponse);
+        metaDataGenerator.setNext(metaDataResponse);
+        response.addMetaData(metaDataResponse.build());
+        return response.build();
+    }
+
     private MongoResponseBuilder(Builder builder) {
         response = builder.queryDocuments;
         metaData = builder.metaData;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/servlet/MongoHttpHandlerHelper.java	Fri Jul 21 09:30:27 2017 -0400
@@ -0,0 +1,276 @@
+/*
+ * 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.servlet;
+
+import com.mongodb.DBObject;
+import com.mongodb.MongoTimeoutException;
+import com.mongodb.MongoWriteException;
+import com.redhat.thermostat.gateway.common.core.auth.keycloak.RealmAuthorizer;
+import com.redhat.thermostat.gateway.common.mongodb.MongoStorageHandler;
+import com.redhat.thermostat.gateway.common.mongodb.ThermostatFields;
+import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
+import com.redhat.thermostat.gateway.common.mongodb.executor.MongoDataResultContainer;
+import com.redhat.thermostat.gateway.common.mongodb.executor.MongoExecutor;
+import com.redhat.thermostat.gateway.common.mongodb.filters.MongoQuery;
+import com.redhat.thermostat.gateway.common.mongodb.filters.MongoRequestFilters;
+import com.redhat.thermostat.gateway.common.mongodb.response.MongoMetaDataGenerator;
+import com.redhat.thermostat.gateway.common.mongodb.response.MongoMetaDataResponseBuilder;
+import com.redhat.thermostat.gateway.common.mongodb.response.MongoResponseBuilder;
+import com.redhat.thermostat.gateway.common.util.HttpResponseExceptionHandler;
+import org.bson.json.JsonParseException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+
+import static com.redhat.thermostat.gateway.common.util.ServiceException.CANNOT_QUERY_REALMS_PROPERTY;
+import static com.redhat.thermostat.gateway.common.util.ServiceException.DATABASE_UNAVAILABLE;
+import static com.redhat.thermostat.gateway.common.util.ServiceException.EXPECTED_JSON_ARRAY;
+import static com.redhat.thermostat.gateway.common.util.ServiceException.MALFORMED_CLIENT_REQUEST;
+
+public class MongoHttpHandlerHelper {
+
+    private final String collectionName;
+    private final MongoExecutor mongoExecutor = new MongoExecutor();
+    private final MongoStorageHandler mongoStorageHandler = new MongoStorageHandler();
+    private final HttpResponseExceptionHandler exceptionHandler = new HttpResponseExceptionHandler();
+
+    public MongoHttpHandlerHelper(String collectionName) {
+        this.collectionName = collectionName;
+        exceptionHandler.add(MongoWriteException.class, MALFORMED_CLIENT_REQUEST)
+                .add(JsonParseException.class, MALFORMED_CLIENT_REQUEST)
+                .add(UnsupportedOperationException.class, MALFORMED_CLIENT_REQUEST)
+                .add(ClassCastException.class, EXPECTED_JSON_ARRAY)
+                .add(MongoTimeoutException.class, DATABASE_UNAVAILABLE)
+                .add(IOException.class, CANNOT_QUERY_REALMS_PROPERTY);
+    }
+
+    /*
+     *  HTTP GET handling
+     */
+
+    public Response handleGetWithJvmID(HttpServletRequest httpServletRequest, ServletContext context, String systemId, String jvmId, Integer limit, Integer offset, String sort, String queries, String includes, String excludes, String returnMetadata) {
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            final MongoQuery querySystemId = new MongoQuery(MongoRequestFilters.buildEq(ThermostatFields.SYSTEM_ID, systemId));
+            final MongoQuery queryJvmId = new MongoQuery(MongoRequestFilters.buildEq(ThermostatFields.JVM_ID, jvmId));
+            String message = mongoStorageHandler.getMany(storage.getDatabase().getCollection(collectionName),
+                    MongoRequestFilters.buildAnd(querySystemId, queryJvmId), 1, 0, null, includes, excludes);
+            return Response.status(Response.Status.OK).entity(message).build();
+        } catch (Exception e) {
+            return Response.status(Response.Status.BAD_REQUEST).build();
+        }
+    }
+
+    public Response handleGetWithSystemID(HttpServletRequest httpServletRequest, ServletContext context, String systemId, Integer limit, Integer offset, String sort, String queries, String includes, String excludes, String returnMetadata) {
+        try {
+            final ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            final MongoQuery systemIdQuery = new MongoQuery(MongoRequestFilters.buildEq(ThermostatFields.SYSTEM_ID, systemId));
+            final MongoQuery query = new MongoQuery(MongoRequestFilters.buildAnd(systemIdQuery, MongoRequestFilters.buildQueriesFilter(queries)));
+            final String message = mongoStorageHandler.getMany(storage.getDatabase().getCollection(collectionName), query, limit, offset, sort, includes, excludes);
+            return Response.status(Response.Status.OK).entity(message).build();
+        } catch (Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+
+    public Response handleGet(HttpServletRequest httpServletRequest, ServletContext context, Integer limit, Integer offset, String sort, String queries, String includes, String excludes, String returnMetadata) {
+        try {
+            boolean metadata = Boolean.valueOf(returnMetadata);
+            RealmAuthorizer realmAuthorizer = (RealmAuthorizer) httpServletRequest.getAttribute(RealmAuthorizer.class.getName());
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+
+            MongoDataResultContainer execResult;
+
+            if (realmAuthorizer != null) {
+                if (realmAuthorizer.readable()) {
+                    execResult = mongoExecutor.execGetRequest(
+                            storage.getDatabase().getCollection(collectionName), limit, offset, sort, queries, includes, excludes, realmAuthorizer.getReadableRealms());
+                } else {
+                    return Response.status(Response.Status.FORBIDDEN).build();
+                }
+            } else {
+                execResult = mongoExecutor.execGetRequest(
+                        storage.getDatabase().getCollection(collectionName), limit, offset, sort, queries, includes, excludes, null);
+            }
+
+            MongoResponseBuilder.Builder response = new MongoResponseBuilder.Builder();
+            response.addQueryDocuments(execResult.getQueryDataResult());
+            if (metadata) {
+                MongoMetaDataResponseBuilder.MetaBuilder metaDataResponse = new MongoMetaDataResponseBuilder.MetaBuilder();
+                MongoMetaDataGenerator metaDataGenerator = new MongoMetaDataGenerator(limit, offset, sort, queries,
+                        includes, excludes, httpServletRequest, execResult);
+
+                metaDataGenerator.setDocAndPayloadCount(metaDataResponse);
+                metaDataGenerator.setPrev(metaDataResponse);
+                metaDataGenerator.setNext(metaDataResponse);
+
+                response.addMetaData(metaDataResponse.build());
+            }
+            return Response.status(Response.Status.OK).entity(response.build()).build();
+        } catch (Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+
+    /*
+     *  HTTP PUT handling
+     */
+
+    public Response handlePutWithSystemId(HttpServletRequest httpServletRequest, ServletContext context, String systemId, String queries, String metadata, String body) {
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            mongoStorageHandler.updateOneSystemObject(storage.getDatabase().getCollection(collectionName), systemId, queries, body);
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+
+    public Response handlePutWithJvmId(HttpServletRequest httpServletRequest, ServletContext context, String systemId, String jvmId, String queries, String metadata, String body) {
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            mongoStorageHandler.updateOneJvmObject(storage.getDatabase().getCollection(collectionName), systemId, jvmId, queries, body);
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+
+    public Response handlePut(HttpServletRequest httpServletRequest, ServletContext context, String queries, String metadata, String body) {
+        try {
+            RealmAuthorizer realmAuthorizer = (RealmAuthorizer) httpServletRequest.getAttribute(RealmAuthorizer.class.getName());
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+
+            if (realmAuthorizer != null) {
+                if (realmAuthorizer.updatable()) {
+                    mongoExecutor.execPutRequest(storage.getDatabase().getCollection(collectionName), body, queries, realmAuthorizer.getUpdatableRealms());
+                } else {
+                    return Response.status(Response.Status.FORBIDDEN).build();
+                }
+            } else {
+                mongoExecutor.execPutRequest(storage.getDatabase().getCollection(collectionName), body, queries, null);
+            }
+
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+
+    /*
+     *  HTTP POST handling
+     */
+
+    public Response handlePostWithSystemID(HttpServletRequest httpServletRequest, ServletContext context, String systemId, String returnMetadata, String body) {
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            mongoStorageHandler.addSystemObjects(storage.getDatabase().getCollection(collectionName, DBObject.class), systemId, body);
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+
+    public Response handlePost(HttpServletRequest httpServletRequest, ServletContext context, String metadata, String body) {
+        try {
+            RealmAuthorizer realmAuthorizer = (RealmAuthorizer) httpServletRequest.getAttribute(RealmAuthorizer.class.getName());
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+
+            if (realmAuthorizer != null) {
+                if (realmAuthorizer.writable()) {
+                    mongoExecutor.execPostRequest(storage.getDatabase().getCollection(collectionName, DBObject.class), body, realmAuthorizer.getWritableRealms());
+                } else {
+                    return Response.status(Response.Status.FORBIDDEN).build();
+                }
+            } else {
+                mongoExecutor.execPostRequest(storage.getDatabase().getCollection(collectionName, DBObject.class), body, null);
+            }
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+
+    /*
+     *  HTTP DELETE handling
+     */
+
+    public Response handleDeleteWithSystemID(HttpServletRequest httpServletRequest, ServletContext context, String systemId, String queries, String metadata) {
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            final MongoQuery query = new MongoQuery(MongoRequestFilters.buildEq(ThermostatFields.SYSTEM_ID, systemId));
+            mongoStorageHandler.deleteMany(storage.getDatabase().getCollection(collectionName), query);
+            return Response.status(Response.Status.OK).build();
+        } catch(Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+
+    public Response handleDeleteWithJvmID(HttpServletRequest httpServletRequest, ServletContext context, String systemId, String jvmId, String queries, String metadata) {
+        try {
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+            final MongoQuery querySystemId = new MongoQuery(MongoRequestFilters.buildEq(ThermostatFields.SYSTEM_ID, systemId));
+            final MongoQuery queryJvmId = new MongoQuery(MongoRequestFilters.buildEq(ThermostatFields.JVM_ID, jvmId));
+            mongoStorageHandler.deleteMany(storage.getDatabase().getCollection(collectionName), MongoRequestFilters.buildAnd(querySystemId, queryJvmId));
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+
+    public Response handleDelete(HttpServletRequest httpServletRequest, ServletContext context, String queries, String metadata) {
+        try {
+            RealmAuthorizer realmAuthorizer = (RealmAuthorizer) httpServletRequest.getAttribute(RealmAuthorizer.class.getName());
+            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+
+            if (realmAuthorizer != null) {
+                if (realmAuthorizer.deletable()) {
+                    mongoExecutor.execDeleteRequest(storage.getDatabase().getCollection(collectionName), queries, realmAuthorizer.getDeletableRealms());
+                } else {
+                    return Response.status(Response.Status.FORBIDDEN).build();
+                }
+            } else {
+                mongoExecutor.execDeleteRequest(storage.getDatabase().getCollection(collectionName), queries, null);
+            }
+            return Response.status(Response.Status.OK).build();
+        } catch (Exception e) {
+            return exceptionHandler.generateResponseForException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/mongodb/src/main/java/com/redhat/thermostat/gateway/common/mongodb/servlet/RequestParameters.java	Fri Jul 21 09:30:27 2017 -0400
@@ -0,0 +1,53 @@
+/*
+ * 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.servlet;
+
+public interface RequestParameters {
+    String SYSTEM_ID = "systemId";
+    String JVM_ID = "jvmId";
+
+    String METADATA = "metadata";
+    String SORT = "sort";
+    String QUERY = "query";
+    String OFFSET = "offset";
+    String LIMIT = "limit";
+    String INCLUDE = "include";
+    String EXCLUDE = "exclude";
+
+    String TIMESTAMP = "timeStamp";
+    String ALIVE_ONLY = "aliveOnly";
+}
--- a/common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoMetaDataGeneratorTest.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoMetaDataGeneratorTest.java	Fri Jul 21 09:30:27 2017 -0400
@@ -42,6 +42,7 @@
 
 import javax.servlet.http.HttpServletRequest;
 
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -56,13 +57,13 @@
     public void setup() {
         HttpServletRequest requestInfo = mock(HttpServletRequest.class);
         when(requestInfo.getRequestURL()).thenReturn(new StringBuffer("127.0.0.1:8080/base/"));
-        when(requestInfo.getQueryString()).thenReturn("l=2&o=2&m=true");
+        when(requestInfo.getQueryString()).thenReturn(RequestParameters.LIMIT + "=2&" + RequestParameters.OFFSET + "=2&" + RequestParameters.METADATA + "=true");
 
         MongoDataResultContainer container = new MongoDataResultContainer();
         container.setRemainingNumQueryDocuments(1);
         container.setGetReqCount(4);
 
-        fullGenerator = new MongoMetaDataGenerator(2, 2, "", "test1==b", "", requestInfo, container);
+        fullGenerator = new MongoMetaDataGenerator(2, 2, "", "test1==b", "", "", requestInfo, container);
         response = new MongoMetaDataResponseBuilder.MetaBuilder();
     }
 
@@ -81,7 +82,7 @@
         String output = response.build().toString();
 
         // {"prev":"127.0.0.1:8080/base/?m=true&l=2&o=0"}
-        String expected = "{\"prev\":\"127.0.0.1:8080/base/?m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d0\"}";
+        String expected = "{\"prev\":\"127.0.0.1:8080/base/?" + RequestParameters.METADATA + "\\u003dtrue\\u0026" + RequestParameters.LIMIT + "\\u003d2\\u0026" + RequestParameters.OFFSET + "\\u003d0\"}";
 
         assertEquals(expected, output);
     }
@@ -92,7 +93,7 @@
         String output = response.build().toString();
 
         // {"payloadCount":1,"next":"127.0.0.1:8080/base/?o=4&l=1&m=true"}//{"payloadCount":1,"next":"127.0.0.1:8080/base/?o=4&l=1&m=true"}
-        String expected = "{\"payloadCount\":1,\"next\":\"127.0.0.1:8080/base/?o\\u003d4\\u0026l\\u003d1\\u0026m\\u003dtrue\"}";
+        String expected = "{\"payloadCount\":1,\"next\":\"127.0.0.1:8080/base/?offset\\u003d4\\u0026limit\\u003d1\\u0026" + RequestParameters.METADATA + "\\u003dtrue\"}";
 
         assertEquals(expected, output);
     }
--- a/common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilderTest.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/common/mongodb/src/test/java/com/redhat/thermostat/gateway/common/mongodb/response/MongoResponseBuilderTest.java	Fri Jul 21 09:30:27 2017 -0400
@@ -75,7 +75,7 @@
 
         FindIterable<Document> iterable = new TestFindIterable<>(list);
 
-        String output = mongoResponseBuilder.queryDocuments(iterable).build();
+        String output = mongoResponseBuilder.addQueryDocuments(iterable).build();
         String expected = "{\"response\":[{\"hello\":\"blob\"},{\"a\":{\"blob\":[\"hi\"]}}]}";
         assertEquals(expected, output);
     }
@@ -84,7 +84,7 @@
     public void testBuildEmptyGetResponse() {
         FindIterable<Document> iterable = new TestFindIterable<>(Collections.<Document>emptyList());
 
-        String output = mongoResponseBuilder.queryDocuments(iterable).build();
+        String output = mongoResponseBuilder.addQueryDocuments(iterable).build();
         String expected = "{\"response\":[]}";
         assertEquals(expected, output);
     }
@@ -99,7 +99,7 @@
 
         FindIterable<Document> iterable = new TestFindIterable<>(list);
 
-        String output = mongoResponseBuilder.queryDocuments(iterable).build();
+        String output = mongoResponseBuilder.addQueryDocuments(iterable).build();
         String expected = "{\"response\":[{\"hello\":\"blob\"},{\"a\":{\"blob\":[\"hi\"]}}]}";
         assertEquals(expected, output);
     }
--- a/services/jvm-gc/src/main/java/com/redhat/thermostat/service/jvm/gc/JvmGcHttpHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/services/jvm-gc/src/main/java/com/redhat/thermostat/service/jvm/gc/JvmGcHttpHandler.java	Fri Jul 21 09:30:27 2017 -0400
@@ -36,13 +36,6 @@
 
 package com.redhat.thermostat.service.jvm.gc;
 
-import static com.redhat.thermostat.gateway.common.util.ServiceException.CANNOT_QUERY_REALMS_PROPERTY;
-import static com.redhat.thermostat.gateway.common.util.ServiceException.DATABASE_UNAVAILABLE;
-import static com.redhat.thermostat.gateway.common.util.ServiceException.EXPECTED_JSON_ARRAY;
-import static com.redhat.thermostat.gateway.common.util.ServiceException.MALFORMED_CLIENT_REQUEST;
-
-import java.io.IOException;
-
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
@@ -57,162 +50,57 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
-import com.mongodb.DBObject;
-import com.mongodb.MongoTimeoutException;
-import com.mongodb.MongoWriteException;
-import com.redhat.thermostat.gateway.common.core.auth.keycloak.RealmAuthorizer;
-import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
-import com.redhat.thermostat.gateway.common.mongodb.executor.MongoDataResultContainer;
-import com.redhat.thermostat.gateway.common.mongodb.executor.MongoExecutor;
-import com.redhat.thermostat.gateway.common.mongodb.response.MongoMetaDataGenerator;
-import com.redhat.thermostat.gateway.common.mongodb.response.MongoMetaDataResponseBuilder;
-import com.redhat.thermostat.gateway.common.mongodb.response.MongoResponseBuilder;
-import com.redhat.thermostat.gateway.common.mongodb.servlet.ServletContextConstants;
-import com.redhat.thermostat.gateway.common.util.HttpResponseExceptionHandler;
-import org.bson.json.JsonParseException;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.MongoHttpHandlerHelper;
 
 @Path("/")
 public class JvmGcHttpHandler {
-    private final MongoExecutor mongoExecutor = new MongoExecutor();
-    private final String collectionName = "jvm-gc";
-    private final HttpResponseExceptionHandler exceptionHandler = new HttpResponseExceptionHandler();
-
-    public JvmGcHttpHandler() {
-        exceptionHandler.add(MongoWriteException.class, MALFORMED_CLIENT_REQUEST)
-                        .add(JsonParseException.class, MALFORMED_CLIENT_REQUEST)
-                        .add(UnsupportedOperationException.class, MALFORMED_CLIENT_REQUEST)
-                        .add(ClassCastException.class, EXPECTED_JSON_ARRAY)
-                        .add(MongoTimeoutException.class, DATABASE_UNAVAILABLE)
-                        .add(IOException.class, CANNOT_QUERY_REALMS_PROPERTY);
-    }
+    private static final String collectionName = "jvm-gc";
+    private final MongoHttpHandlerHelper serviceHelper = new MongoHttpHandlerHelper( collectionName );
 
     @GET
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getJvmGc(@QueryParam("l") @DefaultValue("1") Integer limit,
-                             @QueryParam("o") @DefaultValue("0") Integer offset,
-                             @QueryParam("s") String sort,
-                             @QueryParam("q") String queries,
-                             @QueryParam("p") String projections,
-                             @QueryParam("m") @DefaultValue("false") Boolean metadata,
+    public Response getJvmGc(@QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit,
+                             @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") Integer offset,
+                             @QueryParam(RequestParameters.SORT) String sort,
+                             @QueryParam(RequestParameters.QUERY) String queries,
+                             @QueryParam(RequestParameters.INCLUDE) String includes,
+                             @QueryParam(RequestParameters.EXCLUDE) String excludes,
+                             @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
                              @Context HttpServletRequest httpServletRequest,
                              @Context ServletContext context) {
-        try {
-            RealmAuthorizer realmAuthorizer = (RealmAuthorizer) httpServletRequest.getAttribute(RealmAuthorizer.class.getName());
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            MongoDataResultContainer execResult;
-
-            if (realmAuthorizer != null) {
-                if (realmAuthorizer.readable()) {
-                    execResult = mongoExecutor.execGetRequest(
-                            storage.getDatabase().getCollection(collectionName), limit, offset, sort, queries, projections, realmAuthorizer.getReadableRealms());
-                } else {
-                    return Response.status(Response.Status.FORBIDDEN).build();
-                }
-            } else {
-                execResult = mongoExecutor.execGetRequest(
-                        storage.getDatabase().getCollection(collectionName), limit, offset, sort, queries, projections, null);
-            }
-
-            MongoResponseBuilder.Builder response = new MongoResponseBuilder.Builder();
-            response.queryDocuments(execResult.getQueryDataResult());
-
-            if (metadata) {
-                MongoMetaDataResponseBuilder.MetaBuilder metaDataResponse = new MongoMetaDataResponseBuilder.MetaBuilder();
-                MongoMetaDataGenerator metaDataGenerator = new MongoMetaDataGenerator(limit, offset, sort, queries,
-                        projections, httpServletRequest, execResult);
-
-                metaDataGenerator.setDocAndPayloadCount(metaDataResponse);
-                metaDataGenerator.setPrev(metaDataResponse);
-                metaDataGenerator.setNext(metaDataResponse);
-
-                response.metaData(metaDataResponse.build());
-            }
-            return Response.status(Response.Status.OK).entity(response.build()).build();
-        } catch (Exception e) {
-            return exceptionHandler.generateResponseForException(e);
-        }
+        return serviceHelper.handleGet(httpServletRequest, context, limit, offset, sort, queries, includes, excludes, metadata);
     }
 
     @PUT
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response putJvmGc(String body,
-                             @QueryParam("q") String queries,
-                             @QueryParam("m") @DefaultValue("false") String metadata,
+                             @QueryParam(RequestParameters.QUERY) String queries,
+                             @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
                              @Context ServletContext context,
                              @Context HttpServletRequest httpServletRequest) {
-        try {
-            RealmAuthorizer realmAuthorizer = (RealmAuthorizer) httpServletRequest.getAttribute(RealmAuthorizer.class.getName());
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            if (realmAuthorizer != null) {
-                if (realmAuthorizer.updatable()) {
-                    mongoExecutor.execPutRequest(storage.getDatabase().getCollection(collectionName), body, queries, realmAuthorizer.getUpdatableRealms());
-                } else {
-                    return Response.status(Response.Status.FORBIDDEN).build();
-                }
-            } else {
-                mongoExecutor.execPutRequest(storage.getDatabase().getCollection(collectionName), body, queries, null);
-            }
-
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return exceptionHandler.generateResponseForException(e);
-        }
+        return serviceHelper.handlePut(httpServletRequest, context, queries, metadata, body);
     }
 
     @POST
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response postJvmGc(String body,
-                              @QueryParam("m") @DefaultValue("false") String metadata,
+                              @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
                               @Context ServletContext context,
                               @Context HttpServletRequest httpServletRequest) {
-        try {
-            RealmAuthorizer realmAuthorizer = (RealmAuthorizer) httpServletRequest.getAttribute(RealmAuthorizer.class.getName());
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            if (realmAuthorizer != null) {
-                if (realmAuthorizer.writable()) {
-                    mongoExecutor.execPostRequest(storage.getDatabase().getCollection(collectionName, DBObject.class), body, realmAuthorizer.getWritableRealms());
-                } else {
-                    return Response.status(Response.Status.FORBIDDEN).build();
-                }
-            } else {
-                mongoExecutor.execPostRequest(storage.getDatabase().getCollection(collectionName, DBObject.class), body, null);
-            }
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return exceptionHandler.generateResponseForException(e);
-        }
+        return serviceHelper.handlePost(httpServletRequest, context, metadata, body);
     }
 
     @DELETE
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response deleteJvmGc(@QueryParam("q") String queries,
-                                @QueryParam("m") @DefaultValue("false") String metadata,
+    public Response deleteJvmGc(@QueryParam(RequestParameters.QUERY) String queries,
+                                @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
                                 @Context ServletContext context,
                                 @Context HttpServletRequest httpServletRequest) {
-        try {
-            RealmAuthorizer realmAuthorizer = (RealmAuthorizer) httpServletRequest.getAttribute(RealmAuthorizer.class.getName());
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            if (realmAuthorizer != null) {
-                if (realmAuthorizer.deletable()) {
-                    mongoExecutor.execDeleteRequest(storage.getDatabase().getCollection(collectionName), queries, realmAuthorizer.getDeletableRealms());
-                } else {
-                    return Response.status(Response.Status.FORBIDDEN).build();
-                }
-            } else {
-                mongoExecutor.execDeleteRequest(storage.getDatabase().getCollection(collectionName), queries, null);
-            }
-
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return exceptionHandler.generateResponseForException(e);
-        }
+        return serviceHelper.handleDelete(httpServletRequest, context, queries, metadata);
     }
 }
--- a/services/jvm-gc/src/main/resources/jvm-gc-swagger.yaml	Fri Jul 21 08:30:18 2017 -0400
+++ b/services/jvm-gc/src/main/resources/jvm-gc-swagger.yaml	Fri Jul 21 09:30:27 2017 -0400
@@ -21,7 +21,8 @@
         - $ref: '#/parameters/limit'
         - $ref: '#/parameters/offset'
         - $ref: '#/parameters/sort'
-        - $ref: '#/parameters/projection'
+        - $ref: '#/parameters/include'
+        - $ref: '#/parameters/exclude'
         - $ref: '#/parameters/query'
         - $ref: '#/parameters/metadata'
       responses:
@@ -141,32 +142,49 @@
     schema:
       $ref: '#/definitions/put-body'
   limit:
-    name: l
+    name: limit
     in: query
     description: Limit of items to return. Example '1'
     type: integer
   offset:
-    name: o
+    name: offset
     in: query
     description: Offset of items to return. Example '0'
     type: integer
   sort:
-    name: s
+    name: sort
     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
+    name: query
     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
+  include:
+    name: include
     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.
+    description: >-
+      Inclusion string. Comma separated list of fields to include in the
+      response. Example '?include=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'exclude' parameter. Overriden by
+      'exclude' parameter
     type: string
+    required: false
+  exclude:
+    name: exclude
+    in: query
+    description: >-
+      Exclusion string. Comma separated list of fields to exclude in the
+      response. Example '?exclude=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'include' parameter; takes
+      precedence over 'include' parameter
+    type: string
+    required: false
   metadata:
-    name: m
+    name: metadata
     type: boolean
     in: query
     description: "Metadata flag. If set to 'true', the subsequent request response will return metadata information. If set to 'false', such metadata information will be omitted."
--- a/services/jvm-memory/src/main/java/com/redhat/thermostat/service/jvm/memory/JvmMemoryHttpHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/services/jvm-memory/src/main/java/com/redhat/thermostat/service/jvm/memory/JvmMemoryHttpHandler.java	Fri Jul 21 09:30:27 2017 -0400
@@ -50,106 +50,58 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
-import com.mongodb.DBObject;
 import com.redhat.thermostat.gateway.common.core.model.OffsetParameter;
-import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
-import com.redhat.thermostat.gateway.common.mongodb.executor.MongoDataResultContainer;
-import com.redhat.thermostat.gateway.common.mongodb.executor.MongoExecutor;
-import com.redhat.thermostat.gateway.common.mongodb.response.MongoMetaDataGenerator;
-import com.redhat.thermostat.gateway.common.mongodb.response.MongoMetaDataResponseBuilder;
-import com.redhat.thermostat.gateway.common.mongodb.response.MongoResponseBuilder;
-import com.redhat.thermostat.gateway.common.mongodb.servlet.ServletContextConstants;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.MongoHttpHandlerHelper;
 
 @Path("/")
 public class JvmMemoryHttpHandler {
-    private final MongoExecutor mongoExecutor = new MongoExecutor();
-    private final String collectionName = "jvm-memory";
+    private static final String collectionName = "jvm-memory";
+    private final MongoHttpHandlerHelper serviceHelper = new MongoHttpHandlerHelper( collectionName );
 
     @GET
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getJvmMemory(@QueryParam("l") @DefaultValue("1") Integer limit,
-                                 @QueryParam("o") @DefaultValue("0") OffsetParameter offsetParam,
-                                 @QueryParam("s") String sort,
-                                 @QueryParam("q") String queries,
-                                 @QueryParam("p") String projections,
-                                 @QueryParam("m") @DefaultValue("false") Boolean metadata,
+    public Response getJvmMemory(@QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit,
+                                 @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") OffsetParameter offsetParam,
+                                 @QueryParam(RequestParameters.SORT) String sort,
+                                 @QueryParam(RequestParameters.QUERY) String queries,
+                                 @QueryParam(RequestParameters.INCLUDE) String includes,
+                                 @QueryParam(RequestParameters.EXCLUDE) String excludes,
+                                 @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
                                  @Context ServletContext context,
-                                 @Context HttpServletRequest requestInfo) {
-        try {
-            Integer offset = offsetParam.getValue();
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            MongoDataResultContainer execResult = mongoExecutor.execGetRequest(
-                    storage.getDatabase().getCollection(collectionName), limit, offset, sort, queries, projections, null);
-
-            MongoResponseBuilder.Builder response = new MongoResponseBuilder.Builder();
-            response.queryDocuments(execResult.getQueryDataResult());
-            if (metadata) {
-                MongoMetaDataResponseBuilder.MetaBuilder metaDataResponse = new MongoMetaDataResponseBuilder.MetaBuilder();
-
-                MongoMetaDataGenerator metaDataGenerator = new MongoMetaDataGenerator(limit, offset, sort, queries,
-                        projections, requestInfo, execResult);
-
-                metaDataGenerator.setDocAndPayloadCount(metaDataResponse);
-                metaDataGenerator.setPrev(metaDataResponse);
-                metaDataGenerator.setNext(metaDataResponse);
-
-                response.metaData(metaDataResponse.build());
-            }
-            return Response.status(Response.Status.OK).entity(response.build()).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                                 @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleGet(httpServletRequest, context, limit, offsetParam.getValue(), sort, queries, includes, excludes, metadata);
     }
 
     @PUT
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response putJvmMemory(String body,
-                                 @QueryParam("q") String queries,
-                                 @QueryParam("m") @DefaultValue("false") String metadata,
-                                 @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            mongoExecutor.execPutRequest(storage.getDatabase().getCollection(collectionName), body, queries, null);
-
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                                 @QueryParam(RequestParameters.QUERY) String queries,
+                                 @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                 @Context ServletContext context,
+                                 @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePut(httpServletRequest, context, queries, metadata, body);
     }
 
     @POST
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response postJvmMemory(String body,
-                                  @QueryParam("m") @DefaultValue("false") String metadata,
-                                  @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            mongoExecutor.execPostRequest(storage.getDatabase().getCollection(collectionName, DBObject.class), body, null);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                                  @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                  @Context ServletContext context,
+                                  @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePost(httpServletRequest, context, metadata, body);
     }
 
     @DELETE
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response deleteJvmMemory(@QueryParam("q") String queries,
-                                    @QueryParam("m") @DefaultValue("false") String metadata,
-                                    @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            MongoDataResultContainer delExec = mongoExecutor.execDeleteRequest(storage.getDatabase().getCollection(collectionName), queries, null);
-
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response deleteJvmMemory(@QueryParam(RequestParameters.QUERY) String queries,
+                                    @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                    @Context ServletContext context,
+                                    @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleDelete(httpServletRequest, context, queries, metadata);
     }
 }
--- a/services/jvm-memory/src/main/resources/jvm-memory-swagger.yaml	Fri Jul 21 08:30:18 2017 -0400
+++ b/services/jvm-memory/src/main/resources/jvm-memory-swagger.yaml	Fri Jul 21 09:30:27 2017 -0400
@@ -19,7 +19,8 @@
         - $ref: '#/parameters/limit'
         - $ref: '#/parameters/offset'
         - $ref: '#/parameters/sort'
-        - $ref: '#/parameters/projection'
+        - $ref: '#/parameters/include'
+        - $ref: '#/parameters/exclude'
         - $ref: '#/parameters/query'
         - $ref: '#/parameters/metadata'
       responses:
@@ -172,32 +173,49 @@
     schema:
       $ref: '#/definitions/put-body'
   limit:
-    name: l
+    name: limit
     in: query
     description: Limit of items to return. Example '1'
     type: integer
   offset:
-    name: o
+    name: offset
     in: query
     description: Offset of items to return. Example '0'
     type: integer
   sort:
-    name: s
+    name: sort
     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
+    name: query
     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
+  include:
+    name: include
     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.
+    description: >-
+      Inclusion string. Comma separated list of fields to include in the
+      response. Example '?include=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'exclude' parameter. Overriden by
+      'exclude' parameter
     type: string
+    required: false
+  exclude:
+    name: exclude
+    in: query
+    description: >-
+      Exclusion string. Comma separated list of fields to exclude in the
+      response. Example '?exclude=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'include' parameter; takes
+      precedence over 'include' parameter
+    type: string
+    required: false
   metadata:
-    name: m
+    name: metadata
     type: boolean
     in: query
     description: "Metadata flag. If set to 'true', the subsequent request response will return metadata information. If set to 'false', such metadata information will be omitted."
\ No newline at end of file
--- a/services/jvms/src/main/java/com/redhat/thermostat/service/jvms/http/JvmsHttpHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/services/jvms/src/main/java/com/redhat/thermostat/service/jvms/http/JvmsHttpHandler.java	Fri Jul 21 09:30:27 2017 -0400
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.service.jvms.http;
 
 import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
@@ -50,143 +51,112 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
-import com.mongodb.DBObject;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
 import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
 import com.redhat.thermostat.gateway.common.mongodb.servlet.ServletContextConstants;
-import com.redhat.thermostat.service.jvms.mongo.MongoStorageHandler;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.MongoHttpHandlerHelper;
+import com.redhat.thermostat.service.jvms.mongo.JvmInfoMongoStorageHandler;
 
 @Path("/")
 public class JvmsHttpHandler {
-    private final MongoStorageHandler mongoStorageHandler = new MongoStorageHandler();
-    private final String collectionName = "jvm-info";
+    private static final String collectionName = "jvm-info";
+    private final JvmInfoMongoStorageHandler mongoStorageHandler = new JvmInfoMongoStorageHandler();
+    private final MongoHttpHandlerHelper serviceHelper = new MongoHttpHandlerHelper( collectionName );
 
     @GET
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getJvmInfos(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                @QueryParam(Parameters.LIMIT) @DefaultValue("1") Integer limit,
-                                @QueryParam(Parameters.OFFSET) @DefaultValue("0") Integer offset,
-                                @QueryParam(Parameters.SORT) String sort,
-                                @QueryParam(Parameters.QUERY) String queries,
-                                @QueryParam(Parameters.INCLUDE) String includes,
-                                @QueryParam(Parameters.EXCLUDE) String excludes,
-                                @Context ServletContext context
+    public Response getJvmInfos(@PathParam(RequestParameters.SYSTEM_ID) final String systemId,
+                                @QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit,
+                                @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") final Integer offset,
+                                @QueryParam(RequestParameters.SORT) String sort,
+                                @QueryParam(RequestParameters.QUERY) String queries,
+                                @QueryParam(RequestParameters.INCLUDE) String includes,
+                                @QueryParam(RequestParameters.EXCLUDE) String excludes,
+                                @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                @Context ServletContext context,
+                                @Context HttpServletRequest httpServletRequest
     ) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            String message = mongoStorageHandler.getJvmInfos(storage.getDatabase().getCollection(collectionName), systemId, limit, offset, sort, queries, includes, excludes);
-
-            return Response.status(Response.Status.OK).entity(message).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+        return serviceHelper.handleGetWithSystemID(httpServletRequest, context, systemId, limit, offset, sort, queries, includes, excludes, metadata);
     }
 
     @POST
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response postJvmInfos(String body,
-                                 @PathParam(Parameters.SYSTEM_ID) String systemId,
-                                 @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+                                 @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                 @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                 @Context ServletContext context,
+                                 @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePostWithSystemID(httpServletRequest, context, systemId, metadata, body);
 
-            mongoStorageHandler.addJvmInfos(storage.getDatabase().getCollection(collectionName, DBObject.class), body, systemId);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
     }
 
     @DELETE
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response deleteJvmInfos(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                   @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            mongoStorageHandler.deleteJvmInfos(storage.getDatabase().getCollection(collectionName), systemId);
-
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response deleteJvmInfos(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                   @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                   @Context ServletContext context,
+                                   @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleDeleteWithSystemID(httpServletRequest, context, systemId, null, metadata);
     }
 
     @GET
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}/jvms/{" + Parameters.JVM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}/jvms/{" + RequestParameters.JVM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getJvmInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                               @PathParam(Parameters.JVM_ID) String jvmId,
-                               @QueryParam(Parameters.INCLUDE) String includes,
-                               @QueryParam(Parameters.EXCLUDE) String excludes,
-                               @Context ServletContext context
+    public Response getJvmInfo(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                               @PathParam(RequestParameters.JVM_ID) String jvmId,
+                               @QueryParam(RequestParameters.INCLUDE) String includes,
+                               @QueryParam(RequestParameters.EXCLUDE) String excludes,
+                               @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                               @Context ServletContext context,
+                               @Context HttpServletRequest httpServletRequest
     ) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
+        return serviceHelper.handleGetWithJvmID(httpServletRequest, context, systemId, jvmId, null, null, null, null, includes, excludes, metadata);
+    }
 
-            String message = mongoStorageHandler.getJvmInfo(storage.getDatabase().getCollection(collectionName), systemId, jvmId, includes, excludes);
-
-            return Response.status(Response.Status.OK).entity(message).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
-    }
     @PUT
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}/jvms/{" + Parameters.JVM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}/jvms/{" + RequestParameters.JVM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response putJvmInfo(String body,
-                               @PathParam(Parameters.SYSTEM_ID) String systemId,
-                               @PathParam(Parameters.JVM_ID) String jvmId,
-                               @QueryParam(Parameters.QUERY) String queries,
-                               @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            mongoStorageHandler.updateJvmInfo(storage.getDatabase().getCollection(collectionName), body, systemId, jvmId, queries);
-
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                               @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                               @PathParam(RequestParameters.JVM_ID) String jvmId,
+                               @QueryParam(RequestParameters.QUERY) String queries,
+                               @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                               @Context ServletContext context,
+                               @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePutWithJvmId(httpServletRequest, context, systemId, jvmId, queries, metadata, body);
     }
 
     @DELETE
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}/jvms/{" + Parameters.JVM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}/jvms/{" + RequestParameters.JVM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response deleteJvmInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                  @PathParam(Parameters.JVM_ID) String jvmId,
-                                  @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
-            mongoStorageHandler.deleteJvmInfo(storage.getDatabase().getCollection(collectionName), systemId, jvmId);
-
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response deleteJvmInfo(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                  @PathParam(RequestParameters.JVM_ID) String jvmId,
+                                  @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                  @Context ServletContext context,
+                                  @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleDeleteWithJvmID(httpServletRequest, context, systemId, jvmId, null, metadata);
     }
 
     @PUT
-    @Path("/update/systems/{" + Parameters.SYSTEM_ID + "}/ts/{" + Parameters.TIMESTAMP +"}")
+    @Path("/update/systems/{" + RequestParameters.SYSTEM_ID + "}/ts/{" + RequestParameters.TIMESTAMP +"}")
     public Response putUpdateTimestamp(String body,
-                                       @PathParam(Parameters.SYSTEM_ID) String systemId,
-                                       @PathParam(Parameters.TIMESTAMP) Long timeStamp,
-                                       @Context ServletContext context) {
+                                       @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                       @PathParam(RequestParameters.TIMESTAMP) Long timeStamp,
+                                       @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                       @Context ServletContext context,
+                                       @Context HttpServletRequest httpServletRequest) {
         try {
             ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
             mongoStorageHandler.updateTimestamps(storage.getDatabase().getCollection(collectionName), body, systemId, timeStamp);
-
             return Response.status(Response.Status.OK).build();
         } catch (Exception e) {
             e.printStackTrace();
@@ -198,17 +168,16 @@
     @Path("/tree")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getJvmInfoTree(@QueryParam(Parameters.LIMIT) @DefaultValue("1") Integer limit,
-                                   @QueryParam(Parameters.OFFSET) @DefaultValue("0") Integer offset,
-                                   @QueryParam(Parameters.ALIVE_ONLY) @DefaultValue("true") Boolean aliveOnly,
-                                   @QueryParam(Parameters.INCLUDE) String includes,
-                                   @QueryParam(Parameters.EXCLUDE) String excludes,
+    public Response getJvmInfoTree(@QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit,
+                                   @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") Integer offset,
+                                   @QueryParam(RequestParameters.ALIVE_ONLY) @DefaultValue("true") Boolean aliveOnly,
+                                   @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                   @QueryParam(RequestParameters.INCLUDE) String includes,
+                                   @QueryParam(RequestParameters.EXCLUDE) String excludes,
                                    @Context ServletContext context) {
         try {
             ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-
             String message = mongoStorageHandler.getJvmsTree(storage.getDatabase().getCollection(collectionName), aliveOnly, excludes, includes, limit, offset);
-
             return Response.status(Response.Status.OK).entity(message).build();
         } catch (Exception e) {
             e.printStackTrace();
--- a/services/jvms/src/main/java/com/redhat/thermostat/service/jvms/http/Parameters.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * 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.service.jvms.http;
-
-class Parameters {
-    static final String SYSTEM_ID = "systemId";
-    static final String JVM_ID = "jvmId";
-
-    static final String SORT = "sort";
-    static final String QUERY = "query";
-    static final String OFFSET = "offset";
-    static final String LIMIT = "limit";
-    static final String INCLUDE = "include";
-    static final String EXCLUDE = "exclude";
-
-    static final String TIMESTAMP = "timeStamp";
-    static final String ALIVE_ONLY = "aliveOnly";
-}
--- a/services/jvms/src/main/java/com/redhat/thermostat/service/jvms/mongo/Fields.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * 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.service.jvms.mongo;
-
-class Fields {
-    static final String SYSTEM_ID = "systemId";
-    static final String JVM_ID = "jvmId";
-
-    static final String SET = "set";
-    static final String LAST_UPDATED = "lastUpdated";
-    static final String STOP_TIME = "stopTime";
-
-    static final String RESPONSE = "response";
-    static final String JVMS = "jvms";
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/services/jvms/src/main/java/com/redhat/thermostat/service/jvms/mongo/JvmInfoMongoStorageHandler.java	Fri Jul 21 09:30:27 2017 -0400
@@ -0,0 +1,152 @@
+/*
+ * 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.service.jvms.mongo;
+
+import static com.mongodb.client.model.Filters.and;
+import static com.mongodb.client.model.Filters.eq;
+import static com.mongodb.client.model.Filters.lt;
+import static com.mongodb.client.model.Filters.or;
+import static com.mongodb.client.model.Projections.exclude;
+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.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.redhat.thermostat.gateway.common.mongodb.MongoStorageHandler;
+
+import org.bson.Document;
+import org.bson.conversions.Bson;
+
+import com.mongodb.Block;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.util.JSON;
+
+public class JvmInfoMongoStorageHandler extends MongoStorageHandler {
+
+    private static final String SET_KEY = "$set";
+
+    public void updateTimestamps(MongoCollection<Document> collection, String body, String systemId, Long timeStamp) {
+        final Bson filter;
+        if (body != null && body.length() > 0) {
+            List<String> jvms = (List<String>) JSON.parse(body);
+            List<Bson> jvmFilters = new ArrayList<>();
+            for (String id : jvms) {
+                jvmFilters.add(eq(StorageFields.JVM_ID, id));
+            }
+            filter = and(eq(StorageFields.SYSTEM_ID, systemId), or(jvmFilters));
+        } else {
+            filter = eq(StorageFields.SYSTEM_ID, systemId);
+        }
+
+        final Bson lastUpdated = new Document(StorageFields.LAST_UPDATED, timeStamp);
+        final Bson update = new Document(SET_KEY, lastUpdated);
+        collection.updateMany(filter, update);
+    }
+
+    public String getJvmsTree(MongoCollection<Document> collection, boolean aliveOnly, String excludes, String includes, int limit, int offset) {
+        FindIterable<Document> documents;
+
+        if (aliveOnly) {
+            documents = collection.find(lt(StorageFields.STOP_TIME, 0));
+        } else {
+            documents = collection.find();
+        }
+
+        documents = documents.limit(limit).skip(offset);
+
+        boolean includeSystemId = true;
+        if (excludes != null) {
+            List<String> excludesList = new ArrayList<>(Arrays.asList(excludes.split(",")));
+            if (excludesList.contains(StorageFields.SYSTEM_ID)) {
+                excludesList.remove(StorageFields.SYSTEM_ID);
+                includeSystemId = false;
+            }
+            if (excludesList.size() > 0) {
+                documents = documents.projection(fields(exclude(excludesList), excludeId()));
+            } else {
+                documents = documents.projection(excludeId());
+            }
+        } else if (includes != null) {
+            List<String> includesList = new ArrayList<>(Arrays.asList(includes.split(",")));
+            if (!includesList.contains(StorageFields.SYSTEM_ID)) {
+                includesList.add(StorageFields.SYSTEM_ID);
+                includeSystemId = false;
+            }
+            documents = documents.projection(fields(include(includesList), excludeId()));
+        } else {
+            documents = documents.projection(excludeId());
+        }
+
+        final Map<String, StringBuilder> map = new HashMap<>();
+
+        final boolean finalIncludeSystemId = includeSystemId;
+        documents.forEach(new Block<Document>() {
+            @Override
+            public void apply(Document document) {
+                String systemId = document.getString(StorageFields.SYSTEM_ID);
+                if (!finalIncludeSystemId) {
+                    document.remove(StorageFields.SYSTEM_ID);
+                }
+
+                if (!map.containsKey(systemId)) {
+                    map.put(systemId, new StringBuilder().append("{\"" + StorageFields.SYSTEM_ID + "\":\"" + systemId + "\", \"" + StorageFields.JVMS + "\":["));
+                }
+
+                map.get(systemId).append(document.toJson()).append(",");
+            }
+        });
+
+        StringBuilder responseBuilder = new StringBuilder().append("{ \"" + StorageFields.RESPONSE + "\" : [");
+        if (map.size() > 0) {
+            for (StringBuilder systemBuilder : map.values()) {
+                responseBuilder.append(systemBuilder.deleteCharAt(systemBuilder.length() - 1).toString());
+                responseBuilder.append("]},");
+            }
+            responseBuilder.deleteCharAt(responseBuilder.length() - 1);
+        }
+        responseBuilder.append("]}");
+
+        return responseBuilder.toString();
+    }
+}
--- a/services/jvms/src/main/java/com/redhat/thermostat/service/jvms/mongo/MongoStorageHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-/*
- * 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.service.jvms.mongo;
-
-import static com.mongodb.client.model.Filters.and;
-import static com.mongodb.client.model.Filters.eq;
-import static com.mongodb.client.model.Filters.lt;
-import static com.mongodb.client.model.Filters.or;
-import static com.mongodb.client.model.Projections.exclude;
-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.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.bson.Document;
-import org.bson.conversions.Bson;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.Block;
-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 MongoStorageHandler {
-
-    private static final String SET_KEY = "$set";
-    private final MongoResponseBuilder.Builder mongoResponseBuilder = new MongoResponseBuilder.Builder();
-
-    public String getJvmInfos(MongoCollection<Document> collection, String systemId, Integer limit, Integer offset, String sort, String queries, String includes, String excludes) {
-        Bson baseQuery = eq(Fields.SYSTEM_ID, systemId);
-        FindIterable<Document> documents;
-        if (queries != null) {
-            List<String> queriesList = Arrays.asList(queries.split(","));
-            final Bson query = MongoRequestFilters.buildQueriesFilter(queriesList);
-            documents = collection.find(and(baseQuery, query));
-        } else {
-            documents = collection.find(baseQuery);
-        }
-
-        documents = buildProjection(documents, includes, excludes);
-
-        final Bson sortObject = MongoSortFilters.createSortObject(sort);
-        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit).cursorType(CursorType.NonTailable);
-
-        return mongoResponseBuilder.queryDocuments(documents).build();
-    }
-
-    public String getJvmInfo(MongoCollection<Document> collection, String systemId, String jvmId, String includes, String excludes) {
-        Bson query = and(eq(Fields.JVM_ID, jvmId), eq(Fields.SYSTEM_ID, systemId));
-        FindIterable<Document> documents = collection.find(query);
-
-        documents = buildProjection(documents, includes, excludes);
-
-        documents = documents.limit(1).skip(0).batchSize(1).cursorType(CursorType.NonTailable);
-
-        return mongoResponseBuilder.queryDocuments(documents).build();
-    }
-
-    private FindIterable<Document> buildProjection(FindIterable<Document> documents, String includes, String excludes) {
-        if (excludes != null) {
-            List<String> excludesList = Arrays.asList(excludes.split(","));
-            documents = documents.projection(fields(exclude(excludesList), excludeId()));
-        } else if (includes != null) {
-            List<String> includesList = Arrays.asList(includes.split(","));
-            documents = documents.projection(fields(include(includesList), excludeId()));
-        } else {
-            documents = documents.projection(excludeId());
-        }
-
-        return documents;
-    }
-
-    public void addJvmInfos(MongoCollection<DBObject> collection, String body, String systemId) {
-        if (body.length() > 0) {
-            List<DBObject> inputList = (List<DBObject>) JSON.parse(body);
-            for (DBObject o : inputList) {
-                o.put(Fields.SYSTEM_ID, systemId);
-            }
-            collection.insertMany(inputList);
-        }
-    }
-
-    public void deleteJvmInfos(MongoCollection<Document> collection, String systemId) {
-        Bson query = eq(Fields.SYSTEM_ID, systemId);
-        deleteDocuments(collection, query);
-    }
-    public void deleteJvmInfo(MongoCollection<Document> collection, String systemId, String jvmId) {
-        Bson query = and(eq(Fields.JVM_ID, jvmId), eq(Fields.SYSTEM_ID, systemId));
-        deleteDocuments(collection, query);
-    }
-
-    private void deleteDocuments(MongoCollection<Document> collection, Bson query) {
-        collection.deleteMany(query);
-    }
-
-    public void updateJvmInfo(MongoCollection<Document> collection, String body, String systemId, String jvmId, String queries) {
-        Bson baseQuery = and(eq(Fields.JVM_ID, jvmId), eq(Fields.SYSTEM_ID, systemId));
-
-        BasicDBObject inputObject = (BasicDBObject) JSON.parse(body);
-        BasicDBObject setObject = (BasicDBObject) inputObject.get(Fields.SET);
-        if (setObject.containsField(Fields.JVM_ID) || setObject.containsField(Fields.SYSTEM_ID)) {
-            throw new UnsupportedOperationException("Updating " +  Fields.SYSTEM_ID + " or " + Fields.JVM_ID + " fields is not allowed");
-        }
-
-        final List<String> queriesList;
-        if (queries != null) {
-            queriesList = Arrays.asList(queries.split(","));
-        } else {
-            queriesList = Collections.emptyList();
-        }
-
-        final Bson fields = new Document(SET_KEY, setObject);
-
-        collection.updateMany(and(baseQuery, MongoRequestFilters.buildQueriesFilter(queriesList)), fields);
-    }
-
-    public void updateTimestamps(MongoCollection<Document> collection, String body, String systemId, Long timeStamp) {
-        final Bson filter;
-        if (body != null && body.length() > 0) {
-            List<String> jvms = (List<String>) JSON.parse(body);
-            List<Bson> jvmFilters = new ArrayList<>();
-            for (String id : jvms) {
-                jvmFilters.add(eq(Fields.JVM_ID, id));
-            }
-            filter = and(eq(Fields.SYSTEM_ID, systemId), or(jvmFilters));
-        } else {
-            filter = eq(Fields.SYSTEM_ID, systemId);
-        }
-
-        final Bson lastUpdated = new Document(Fields.LAST_UPDATED, timeStamp);
-        final Bson update = new Document(SET_KEY, lastUpdated);
-        collection.updateMany(filter, update);
-    }
-
-    public String getJvmsTree(MongoCollection<Document> collection, boolean aliveOnly, String excludes, String includes, int limit, int offset) {
-        FindIterable<Document> documents;
-
-        if (aliveOnly) {
-            documents = collection.find(lt(Fields.STOP_TIME, 0));
-        } else {
-            documents = collection.find();
-        }
-
-        documents = documents.limit(limit).skip(offset);
-
-        boolean includeSystemId = true;
-        if (excludes != null) {
-            List<String> excludesList = new ArrayList<>(Arrays.asList(excludes.split(",")));
-            if (excludesList.contains(Fields.SYSTEM_ID)) {
-                excludesList.remove(Fields.SYSTEM_ID);
-                includeSystemId = false;
-            }
-            if (excludesList.size() > 0) {
-                documents = documents.projection(fields(exclude(excludesList), excludeId()));
-            } else {
-                documents = documents.projection(excludeId());
-            }
-        } else if (includes != null) {
-            List<String> includesList = new ArrayList<>(Arrays.asList(includes.split(",")));
-            if (!includesList.contains(Fields.SYSTEM_ID)) {
-                includesList.add(Fields.SYSTEM_ID);
-                includeSystemId = false;
-            }
-            documents = documents.projection(fields(include(includesList), excludeId()));
-        } else {
-            documents = documents.projection(excludeId());
-        }
-
-        final Map<String, StringBuilder> map = new HashMap<>();
-
-        final boolean finalIncludeSystemId = includeSystemId;
-        documents.forEach(new Block<Document>() {
-            @Override
-            public void apply(Document document) {
-                String systemId = document.getString(Fields.SYSTEM_ID);
-                if (!finalIncludeSystemId) {
-                    document.remove(Fields.SYSTEM_ID);
-                }
-
-                if (!map.containsKey(systemId)) {
-                    map.put(systemId, new StringBuilder().append("{\"" + Fields.SYSTEM_ID + "\":\"" + systemId + "\", \"" + Fields.JVMS + "\":["));
-                }
-
-                map.get(systemId).append(document.toJson()).append(",");
-            }
-        });
-
-        StringBuilder responseBuilder = new StringBuilder().append("{ \"" + Fields.RESPONSE + "\" : [");
-        if (map.size() > 0) {
-            for (StringBuilder systemBuilder : map.values()) {
-                responseBuilder.append(systemBuilder.deleteCharAt(systemBuilder.length() - 1).toString());
-                responseBuilder.append("]},");
-            }
-            responseBuilder.deleteCharAt(responseBuilder.length() - 1);
-        }
-        responseBuilder.append("]}");
-
-        return responseBuilder.toString();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/services/jvms/src/main/java/com/redhat/thermostat/service/jvms/mongo/StorageFields.java	Fri Jul 21 09:30:27 2017 -0400
@@ -0,0 +1,48 @@
+/*
+ * 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.service.jvms.mongo;
+
+import com.redhat.thermostat.gateway.common.mongodb.ThermostatFields;
+
+public interface StorageFields extends ThermostatFields {
+
+    String LAST_UPDATED = "lastUpdated";
+    String STOP_TIME = "stopTime";
+
+    String RESPONSE = "response";
+    String JVMS = "jvms";
+}
--- a/services/system-cpu/src/main/java/com/redhat/thermostat/service/system/cpu/http/Parameters.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * 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.service.system.cpu.http;
-
-class Parameters {
-    static final String SYSTEM_ID = "systemId";
-
-    static final String SORT = "sort";
-    static final String QUERY = "query";
-    static final String OFFSET = "offset";
-    static final String LIMIT = "limit";
-    static final String INCLUDE = "include";
-    static final String EXCLUDE = "exclude";
-
-    static final String TIMESTAMP = "timeStamp";
-}
--- a/services/system-cpu/src/main/java/com/redhat/thermostat/service/system/cpu/http/SystemInfoCPUHttpHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/services/system-cpu/src/main/java/com/redhat/thermostat/service/system/cpu/http/SystemInfoCPUHttpHandler.java	Fri Jul 21 09:30:27 2017 -0400
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.service.system.cpu.http;
 
 import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
@@ -50,84 +51,65 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
-
-import com.mongodb.DBObject;
-import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
-import com.redhat.thermostat.gateway.common.mongodb.servlet.ServletContextConstants;
-import com.redhat.thermostat.service.system.cpu.mongo.MongoStorageHandler;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.MongoHttpHandlerHelper;
 
 @Path("/")
 public class SystemInfoCPUHttpHandler {
-    private final MongoStorageHandler mongoStorageHandler = new MongoStorageHandler();
     private final String collectionName = "cpu-info";
+    private final MongoHttpHandlerHelper serviceHelper = new MongoHttpHandlerHelper( collectionName );
 
     @GET
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getCPUInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                  @QueryParam(Parameters.LIMIT) @DefaultValue("1") Integer limit,
-                                  @QueryParam(Parameters.OFFSET) @DefaultValue("0") Integer offset,
-                                  @QueryParam(Parameters.SORT) String sort,
-                                  @QueryParam(Parameters.INCLUDE) String includes,
-                                  @QueryParam(Parameters.EXCLUDE) String excludes,
-                                  @Context ServletContext context
-    ) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            String message = mongoStorageHandler.getOne(storage.getDatabase().getCollection(collectionName), systemId, limit, offset, sort, includes, excludes);
-            return Response.status(Response.Status.OK).entity(message).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response getCPUInfo(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                               @QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit,
+                               @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") Integer offset,
+                               @QueryParam(RequestParameters.SORT) String sort,
+                               @QueryParam(RequestParameters.QUERY) String queries,
+                               @QueryParam(RequestParameters.INCLUDE) String includes,
+                               @QueryParam(RequestParameters.EXCLUDE) String excludes,
+                               @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                               @Context ServletContext context,
+                               @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleGetWithSystemID(httpServletRequest, context, systemId, limit, offset, sort, queries, includes, excludes, metadata);
     }
 
     @PUT
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response putCPUInfo(String body,
-                                  @PathParam(Parameters.SYSTEM_ID) String systemId,
-                                  @QueryParam(Parameters.QUERY) String queries,
-                                  @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.updateOne(storage.getDatabase().getCollection(collectionName), body, systemId, queries);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                               @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                               @QueryParam(RequestParameters.QUERY) String queries,
+                               @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                               @Context ServletContext context,
+                               @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePutWithSystemId(httpServletRequest, context, systemId, queries, metadata, body);
     }
 
     @POST
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response postCPUInfo(String body,
-                                   @PathParam(Parameters.SYSTEM_ID) String systemId,
-                                   @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.addMany(storage.getDatabase().getCollection(collectionName, DBObject.class), body, systemId);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                                @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                @Context ServletContext context,
+                                @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePostWithSystemID(httpServletRequest, context, systemId, metadata, body);
     }
 
     @DELETE
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response deleteCPUInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                     @QueryParam(Parameters.QUERY) String queries,
-                                     @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.delete(storage.getDatabase().getCollection(collectionName), systemId);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response deleteCPUInfo(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                  @QueryParam(RequestParameters.QUERY) String queries,
+                                  @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                  @Context ServletContext context,
+                                  @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleDeleteWithSystemID(httpServletRequest, context, systemId, queries, metadata);
     }
 }
--- a/services/system-cpu/src/main/java/com/redhat/thermostat/service/system/cpu/mongo/Fields.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * 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.service.system.cpu.mongo;
-
-class Fields {
-    static final String SYSTEM_ID = "systemId";
-
-    static final String SET = "set";
-    static final String LAST_UPDATED = "lastUpdated";
-    static final String STOP_TIME = "stopTime";
-
-    static final String RESPONSE = "response";
-    static final String SYSTEMS = "systems";
-}
--- a/services/system-cpu/src/main/java/com/redhat/thermostat/service/system/cpu/mongo/MongoStorageHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * 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.service.system.cpu.mongo;
-
-import static com.mongodb.client.model.Filters.and;
-import static com.mongodb.client.model.Filters.eq;
-import static com.mongodb.client.model.Projections.exclude;
-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 MongoStorageHandler {
-
-    private final MongoResponseBuilder.Builder mongoResponseBuilder = new MongoResponseBuilder.Builder();
-
-    public String getMany(MongoCollection<Document> collection, Integer limit, Integer offset, String sort, String queries, String includes, String excludes) {
-        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();
-        }
-
-        documents = buildProjection(documents, includes, excludes);
-
-        final Bson sortObject = MongoSortFilters.createSortObject(sort);
-        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit).cursorType(CursorType.NonTailable);
-
-        return mongoResponseBuilder.queryDocuments(documents).build();
-    }
-
-    public String getOne(MongoCollection<Document> collection, String systemId, Integer limit, Integer offset, String sort, String includes, String excludes) {
-        Bson query = eq(Fields.SYSTEM_ID, systemId);
-        FindIterable<Document> documents = collection.find(query);
-
-        documents = buildProjection(documents, includes, excludes);
-
-        final Bson sortObject = MongoSortFilters.createSortObject(sort);
-        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit + offset).cursorType(CursorType.NonTailable);
-
-        return mongoResponseBuilder.queryDocuments(documents).build();
-    }
-
-    private FindIterable<Document> buildProjection(FindIterable<Document> documents, String includes, String excludes) {
-        if (excludes != null) {
-            List<String> excludesList = Arrays.asList(excludes.split(","));
-            documents = documents.projection(fields(exclude(excludesList), excludeId()));
-        } else if (includes != null) {
-            List<String> includesList = Arrays.asList(includes.split(","));
-            documents = documents.projection(fields(include(includesList), excludeId()));
-        } else {
-            documents = documents.projection(excludeId());
-        }
-
-        return documents;
-    }
-
-    public void addMany(MongoCollection<DBObject> collection, String body, String systemId) {
-        if (body.length() > 0) {
-            List<DBObject> inputList = (List<DBObject>) JSON.parse(body);
-            for (DBObject o : inputList) {
-                o.put(Fields.SYSTEM_ID, systemId);
-            }
-            collection.insertMany(inputList);
-        }
-    }
-
-    public void delete(MongoCollection<Document> collection, String systemId) {
-        Bson query = eq(Fields.SYSTEM_ID, systemId);
-        deleteDocuments(collection, query);
-    }
-
-    private void deleteDocuments(MongoCollection<Document> collection, Bson query) {
-        collection.deleteMany(query);
-    }
-
-    public void updateOne(MongoCollection<Document> collection, String body, String systemId, String queries) {
-        Bson baseQuery = eq(Fields.SYSTEM_ID, systemId);
-
-        BasicDBObject inputObject = (BasicDBObject) JSON.parse(body);
-        BasicDBObject setObject = (BasicDBObject) inputObject.get(Fields.SET);
-        if (setObject.containsField(Fields.SYSTEM_ID)) {
-            throw new UnsupportedOperationException("Updating " +  Fields.SYSTEM_ID + " fields is not allowed");
-        }
-
-        final List<String> queriesList;
-        if (queries != null) {
-            queriesList = Arrays.asList(queries.split(","));
-        } else {
-            queriesList = Collections.emptyList();
-        }
-
-        final Bson fields = new Document("$set", setObject);
-
-        collection.updateMany(and(baseQuery, MongoRequestFilters.buildQueriesFilter(queriesList)), fields);
-    }
-}
--- a/services/system-memory/src/main/java/com/redhat/thermostat/service/system/memory/http/Parameters.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * 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.service.system.memory.http;
-
-class Parameters {
-    static final String SYSTEM_ID = "systemId";
-
-    static final String SORT = "sort";
-    static final String QUERY = "query";
-    static final String OFFSET = "offset";
-    static final String LIMIT = "limit";
-    static final String INCLUDE = "include";
-    static final String EXCLUDE = "exclude";
-
-    static final String TIMESTAMP = "timeStamp";
-}
--- a/services/system-memory/src/main/java/com/redhat/thermostat/service/system/memory/http/SystemMemoryHttpHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/services/system-memory/src/main/java/com/redhat/thermostat/service/system/memory/http/SystemMemoryHttpHandler.java	Fri Jul 21 09:30:27 2017 -0400
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.service.system.memory.http;
 
 import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
@@ -50,84 +51,65 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
-
-import com.mongodb.DBObject;
-import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
-import com.redhat.thermostat.gateway.common.mongodb.servlet.ServletContextConstants;
-import com.redhat.thermostat.service.system.memory.mongo.MongoStorageHandler;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.MongoHttpHandlerHelper;
 
 @Path("/")
 public class SystemMemoryHttpHandler {
-    private final MongoStorageHandler mongoStorageHandler = new MongoStorageHandler();
     private final String collectionName = "memory-info";
+    private final MongoHttpHandlerHelper serviceHelper = new MongoHttpHandlerHelper( collectionName );
 
     @GET
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getCPUInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                  @QueryParam(Parameters.LIMIT) @DefaultValue("1") Integer limit,
-                                  @QueryParam(Parameters.OFFSET) @DefaultValue("0") Integer offset,
-                                  @QueryParam(Parameters.SORT) String sort,
-                                  @QueryParam(Parameters.INCLUDE) String includes,
-                                  @QueryParam(Parameters.EXCLUDE) String excludes,
-                                  @Context ServletContext context
-    ) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            String message = mongoStorageHandler.getOne(storage.getDatabase().getCollection(collectionName), systemId, limit, offset, sort, includes, excludes);
-            return Response.status(Response.Status.OK).entity(message).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response getCPUInfo(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                               @QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit,
+                               @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") Integer offset,
+                               @QueryParam(RequestParameters.SORT) String sort,
+                               @QueryParam(RequestParameters.QUERY) String queries,
+                               @QueryParam(RequestParameters.INCLUDE) String includes,
+                               @QueryParam(RequestParameters.EXCLUDE) String excludes,
+                               @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                               @Context ServletContext context,
+                               @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleGetWithSystemID(httpServletRequest, context, systemId, limit, offset, sort, queries, includes, excludes, metadata);
     }
 
     @PUT
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response putCPUInfo(String body,
-                                  @PathParam(Parameters.SYSTEM_ID) String systemId,
-                                  @QueryParam(Parameters.QUERY) String queries,
-                                  @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.updateOne(storage.getDatabase().getCollection(collectionName), body, systemId, queries);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                               @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                               @QueryParam(RequestParameters.QUERY) String queries,
+                               @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                               @Context ServletContext context,
+                               @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePutWithSystemId(httpServletRequest, context, systemId, queries, metadata, body);
     }
 
     @POST
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response postCPUInfo(String body,
-                                   @PathParam(Parameters.SYSTEM_ID) String systemId,
-                                   @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.addMany(storage.getDatabase().getCollection(collectionName, DBObject.class), body, systemId);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                                @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                @Context ServletContext context,
+                                @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePostWithSystemID(httpServletRequest, context, systemId, metadata, body);
     }
 
     @DELETE
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response deleteCPUInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                     @QueryParam(Parameters.QUERY) String queries,
-                                     @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.delete(storage.getDatabase().getCollection(collectionName), systemId);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response deleteCPUInfo(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                  @QueryParam(RequestParameters.QUERY) String queries,
+                                  @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                  @Context ServletContext context,
+                                  @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleDeleteWithSystemID(httpServletRequest, context, systemId, queries, metadata);
     }
 }
--- a/services/system-memory/src/main/java/com/redhat/thermostat/service/system/memory/mongo/Fields.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * 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.service.system.memory.mongo;
-
-class Fields {
-    static final String SYSTEM_ID = "systemId";
-    static final String SET = "set";
-    static final String LAST_UPDATED = "lastUpdated";
-    static final String RESPONSE = "response";
-}
--- a/services/system-memory/src/main/java/com/redhat/thermostat/service/system/memory/mongo/MongoStorageHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * 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.service.system.memory.mongo;
-
-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;
-import org.bson.Document;
-import org.bson.conversions.Bson;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static com.mongodb.client.model.Filters.and;
-import static com.mongodb.client.model.Filters.eq;
-import static com.mongodb.client.model.Filters.or;
-import static com.mongodb.client.model.Projections.exclude;
-import static com.mongodb.client.model.Projections.excludeId;
-import static com.mongodb.client.model.Projections.fields;
-import static com.mongodb.client.model.Projections.include;
-
-public class MongoStorageHandler {
-
-    private final MongoResponseBuilder.Builder mongoResponseBuilder = new MongoResponseBuilder.Builder();
-
-    public String getOne(MongoCollection<Document> collection, String systemId, Integer limit, Integer offset, String sort, String includes, String excludes) {
-        Bson query = eq(Fields.SYSTEM_ID, systemId);
-        FindIterable<Document> documents = collection.find(query);
-
-        documents = buildProjection(documents, includes, excludes);
-
-        final Bson sortObject = MongoSortFilters.createSortObject(sort);
-        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit + offset).cursorType(CursorType.NonTailable);
-
-        return mongoResponseBuilder.queryDocuments(documents).build();
-    }
-
-    private FindIterable<Document> buildProjection(FindIterable<Document> documents, String includes, String excludes) {
-        if (excludes != null) {
-            List<String> excludesList = Arrays.asList(excludes.split(","));
-            documents = documents.projection(fields(exclude(excludesList), excludeId()));
-        } else if (includes != null) {
-            List<String> includesList = Arrays.asList(includes.split(","));
-            documents = documents.projection(fields(include(includesList), excludeId()));
-        } else {
-            documents = documents.projection(excludeId());
-        }
-
-        return documents;
-    }
-
-    public void addMany(MongoCollection<DBObject> collection, String body, String systemId) {
-        if (body.length() > 0) {
-            List<DBObject> inputList = (List<DBObject>) JSON.parse(body);
-            for (DBObject o : inputList) {
-                o.put(Fields.SYSTEM_ID, systemId);
-            }
-            collection.insertMany(inputList);
-        }
-    }
-
-    public void delete(MongoCollection<Document> collection, String systemId) {
-        Bson query = eq(Fields.SYSTEM_ID, systemId);
-        deleteDocuments(collection, query);
-    }
-
-    private void deleteDocuments(MongoCollection<Document> collection, Bson query) {
-        collection.deleteMany(query);
-    }
-
-    public void updateOne(MongoCollection<Document> collection, String body, String systemId, String queries) {
-        Bson baseQuery = eq(Fields.SYSTEM_ID, systemId);
-
-        BasicDBObject inputObject = (BasicDBObject) JSON.parse(body);
-        BasicDBObject setObject = (BasicDBObject) inputObject.get(Fields.SET);
-        if (setObject.containsField(Fields.SYSTEM_ID)) {
-            throw new UnsupportedOperationException("Updating " +  Fields.SYSTEM_ID + " fields is not allowed");
-        }
-
-        final List<String> queriesList;
-        if (queries != null) {
-            queriesList = Arrays.asList(queries.split(","));
-        } else {
-            queriesList = Collections.emptyList();
-        }
-
-        final Bson fields = new Document("$set", setObject);
-
-        collection.updateMany(and(baseQuery, MongoRequestFilters.buildQueriesFilter(queriesList)), fields);
-    }
-}
--- a/services/system-memory/src/main/resources/memory-info-swagger.yaml	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-swagger: '2.0'
-info:
-  version: 0.0.1
-  title: Thermostat Web Gateway Memory Info 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: /system-memory/0.0.1
-paths:
-  /systems/{systemId}:
-    parameters:
-      - $ref: '#/parameters/system-id'
-    get:
-      description: Get Memory information for system {systemId}.
-      parameters:
-        - $ref: '#/parameters/limit'
-        - $ref: '#/parameters/offset'
-        - $ref: '#/parameters/sort'
-        - $ref: '#/parameters/include'
-        - $ref: '#/parameters/exclude'
-        - $ref: '#/parameters/query'
-      responses:
-        '200':
-          description: OK
-          schema:
-            $ref: '#/definitions/memory-info-get-response'
-    put:
-      description: Update Memory information for system {systemId}.
-      parameters:
-        - $ref: '#/parameters/memory-info-put-body'
-        - $ref: '#/parameters/query'
-      responses:
-        '200':
-          description: OK
-    post:
-      description: Add Memory information for system {systemId}
-      parameters:
-        - $ref: '#/parameters/memory-info-array'
-      responses:
-        '200':
-          description: OK
-    delete:
-      description: Delete Memory information for system ID {systemId}.
-      parameters:
-        - $ref: '#/parameters/query'
-      responses:
-        '200':
-          description: OK
-definitions:
-  memory-info-get-response:
-    type: object
-    properties:
-      response:
-        $ref: '#/definitions/memory-info-array'
-  memory-info-array:
-    type: array
-    items:
-      $ref: '#/definitions/memory-info'
-  memory-info:
-    type: object
-    properties:
-      systemId:
-        type: string
-      agentId:
-        type: string
-      timestamp:
-        type: integer
-        format: int64
-      total:
-        type: integer
-        format: int64
-      free:
-        type: integer
-        format: int64
-      buffers:
-        type: integer
-        format: int64
-      cached:
-        type: integer
-        format: int64
-      swapTotal:
-        type: integer
-        format: int64
-      swapFree:
-        type: integer
-        format: int64
-      commitLimit:
-        type: integer
-        format: int64
-  memory-info-put-body:
-    type: object
-    properties:
-      "set":
-        type: object
-parameters:
-  system-id:
-    name: systemId
-    in: path
-    required: true
-    type: string
-  memory-info-array:
-    name: memory-info-array
-    in: body
-    description: The system Memory information
-    required: true
-    schema:
-      $ref: '#/definitions/memory-info-array'
-  memory-info-put-body:
-    name: body
-    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.
-      Must not include 'systemId' field. Example { "set" : {
-      "field" : "value", "field2":{"object":"item"} }
-    required: true
-    schema:
-      $ref: '#/definitions/memory-info-put-body'
-  limit:
-    name: limit
-    in: query
-    description: Limit of items to return. Example '1'
-    type: integer
-    required: false
-    default: 1
-  offset:
-    name: offset
-    in: query
-    description: Offset of items to return. Example '0'
-    type: integer
-    required: true
-    default: 0
-  sort:
-    name: sort
-    in: query
-    description: Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.
-    type: string
-    required: false
-  query:
-    name: query
-    in: query
-    description: Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?query=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
-    required: false
-  include:
-    name: include
-    in: query
-    description: >-
-      Inclusion string. Comma separated list of fields to include in the
-      response. Example '?include=a,b' Fields use dot notation for embedded
-      documents. Example 'outer.inner' refers to field inner contained in field
-      outer. Cannot be used in combination with 'exclude' parameter Overriden by
-      'exclude' parameter
-    type: string
-    required: false
-  exclude:
-    name: exclude
-    in: query
-    description: >-
-      Exclusion string. Comma separated list of fields to exclude in the
-      response. Example '?exclude=a,b' Fields use dot notation for embedded
-      documents. Example 'outer.inner' refers to field inner contained in field
-      outer. Cannot be used in combination with 'include' parameter; takes
-      precedence over 'include' parameter
-    type: string
-    required: false
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/services/system-memory/src/main/resources/system-memory-swagger.yaml	Fri Jul 21 09:30:27 2017 -0400
@@ -0,0 +1,171 @@
+swagger: '2.0'
+info:
+  version: 0.0.1
+  title: Thermostat Web Gateway System Memory Info 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: /system-memory/0.0.1
+paths:
+  /systems/{systemId}:
+    parameters:
+      - $ref: '#/parameters/system-id'
+    get:
+      description: Get Memory information for system {systemId}.
+      parameters:
+        - $ref: '#/parameters/limit'
+        - $ref: '#/parameters/offset'
+        - $ref: '#/parameters/sort'
+        - $ref: '#/parameters/include'
+        - $ref: '#/parameters/exclude'
+        - $ref: '#/parameters/query'
+      responses:
+        '200':
+          description: OK
+          schema:
+            $ref: '#/definitions/memory-info-get-response'
+    put:
+      description: Update Memory information for system {systemId}.
+      parameters:
+        - $ref: '#/parameters/memory-info-put-body'
+        - $ref: '#/parameters/query'
+      responses:
+        '200':
+          description: OK
+    post:
+      description: Add Memory information for system {systemId}
+      parameters:
+        - $ref: '#/parameters/memory-info-array'
+      responses:
+        '200':
+          description: OK
+    delete:
+      description: Delete Memory information for system ID {systemId}.
+      parameters:
+        - $ref: '#/parameters/query'
+      responses:
+        '200':
+          description: OK
+definitions:
+  memory-info-get-response:
+    type: object
+    properties:
+      response:
+        $ref: '#/definitions/memory-info-array'
+  memory-info-array:
+    type: array
+    items:
+      $ref: '#/definitions/memory-info'
+  memory-info:
+    type: object
+    properties:
+      systemId:
+        type: string
+      agentId:
+        type: string
+      timestamp:
+        type: integer
+        format: int64
+      total:
+        type: integer
+        format: int64
+      free:
+        type: integer
+        format: int64
+      buffers:
+        type: integer
+        format: int64
+      cached:
+        type: integer
+        format: int64
+      swapTotal:
+        type: integer
+        format: int64
+      swapFree:
+        type: integer
+        format: int64
+      commitLimit:
+        type: integer
+        format: int64
+  memory-info-put-body:
+    type: object
+    properties:
+      "set":
+        type: object
+parameters:
+  system-id:
+    name: systemId
+    in: path
+    required: true
+    type: string
+  memory-info-array:
+    name: memory-info-array
+    in: body
+    description: The system Memory information
+    required: true
+    schema:
+      $ref: '#/definitions/memory-info-array'
+  memory-info-put-body:
+    name: body
+    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.
+      Must not include 'systemId' field. Example { "set" : {
+      "field" : "value", "field2":{"object":"item"} }
+    required: true
+    schema:
+      $ref: '#/definitions/memory-info-put-body'
+  limit:
+    name: limit
+    in: query
+    description: Limit of items to return. Example '1'
+    type: integer
+    required: false
+    default: 1
+  offset:
+    name: offset
+    in: query
+    description: Offset of items to return. Example '0'
+    type: integer
+    required: true
+    default: 0
+  sort:
+    name: sort
+    in: query
+    description: Sort string. Comma separated list of fields prefixed with '+' for ascending or '-' for descending. Example '?sort=+a,-b' Fields use dot notation for embedded documents. Example 'outer.inner' refers to field inner contained in field outer.
+    type: string
+    required: false
+  query:
+    name: query
+    in: query
+    description: Query string. Comma separated list of key, comparator, value pairs. Comparator supports '==', '<=', '>=', '<', '>', '!='. Example '?query=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
+    required: false
+  include:
+    name: include
+    in: query
+    description: >-
+      Inclusion string. Comma separated list of fields to include in the
+      response. Example '?include=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'exclude' parameter. Overriden by
+      'exclude' parameter
+    type: string
+    required: false
+  exclude:
+    name: exclude
+    in: query
+    description: >-
+      Exclusion string. Comma separated list of fields to exclude in the
+      response. Example '?exclude=a,b' Fields use dot notation for embedded
+      documents. Example 'outer.inner' refers to field inner contained in field
+      outer. Cannot be used in combination with 'include' parameter; takes
+      precedence over 'include' parameter
+    type: string
+    required: false
--- a/services/system-network/src/main/java/com/redhat/thermostat/service/system/network/http/Parameters.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * 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.service.system.network.http;
-
-class Parameters {
-    static final String SYSTEM_ID = "systemId";
-
-    static final String SORT = "sort";
-    static final String QUERY = "query";
-    static final String OFFSET = "offset";
-    static final String LIMIT = "limit";
-    static final String INCLUDE = "include";
-    static final String EXCLUDE = "exclude";
-
-    static final String TIMESTAMP = "timeStamp";
-}
--- a/services/system-network/src/main/java/com/redhat/thermostat/service/system/network/http/SystemNetworkHttpHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/services/system-network/src/main/java/com/redhat/thermostat/service/system/network/http/SystemNetworkHttpHandler.java	Fri Jul 21 09:30:27 2017 -0400
@@ -36,12 +36,11 @@
 
 package com.redhat.thermostat.service.system.network.http;
 
-import com.mongodb.DBObject;
-import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
-import com.redhat.thermostat.gateway.common.mongodb.servlet.ServletContextConstants;
-import com.redhat.thermostat.service.system.network.mongo.MongoStorageHandler;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.MongoHttpHandlerHelper;
 
 import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
@@ -57,76 +56,60 @@
 
 @Path("/")
 public class SystemNetworkHttpHandler {
-    private final MongoStorageHandler mongoStorageHandler = new MongoStorageHandler();
-    private final String collectionName = "network-info";
+    private static final String collectionName = "network-info";
+    private final MongoHttpHandlerHelper serviceHelper = new MongoHttpHandlerHelper( collectionName );
 
     @GET
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getNetworkInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                               @QueryParam(Parameters.LIMIT) @DefaultValue("1") Integer limit,
-                               @QueryParam(Parameters.OFFSET) @DefaultValue("0") Integer offset,
-                               @QueryParam(Parameters.SORT) String sort,
-                               @QueryParam(Parameters.INCLUDE) String includes,
-                               @QueryParam(Parameters.EXCLUDE) String excludes,
-                               @Context ServletContext context
-    ) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            String message = mongoStorageHandler.getOne(storage.getDatabase().getCollection(collectionName), systemId, limit, offset, sort, includes, excludes);
-            return Response.status(Response.Status.OK).entity(message).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response get(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                        @QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit,
+                        @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") Integer offset,
+                        @QueryParam(RequestParameters.SORT) String sort,
+                        @QueryParam(RequestParameters.QUERY) String queries,
+                        @QueryParam(RequestParameters.INCLUDE) String includes,
+                        @QueryParam(RequestParameters.EXCLUDE) String excludes,
+                        @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                        @Context ServletContext context,
+                        @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleGetWithSystemID(httpServletRequest, context, systemId, limit, offset, sort, queries, includes, excludes, metadata);
     }
 
     @PUT
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response putNetworkInfo(String body,
-                               @PathParam(Parameters.SYSTEM_ID) String systemId,
-                               @QueryParam(Parameters.QUERY) String queries,
-                               @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.updateOne(storage.getDatabase().getCollection(collectionName), body, systemId, queries);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response put(String body,
+                        @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                        @QueryParam(RequestParameters.QUERY) String queries,
+                        @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                        @Context ServletContext context,
+                        @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePutWithSystemId(httpServletRequest, context, systemId, queries, metadata, body);
     }
 
     @POST
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response postNetworkInfo(String body,
-                                @PathParam(Parameters.SYSTEM_ID) String systemId,
-                                @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.addOne(storage.getDatabase().getCollection(collectionName, DBObject.class), body, systemId);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response post(String body,
+                         @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                         @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                         @Context ServletContext context,
+                         @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePostWithSystemID(httpServletRequest, context, systemId, metadata, body);
     }
 
     @DELETE
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response deleteNetworkInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                  @QueryParam(Parameters.QUERY) String queries,
-                                  @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.delete(storage.getDatabase().getCollection(collectionName), systemId);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response delete(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                           @QueryParam(RequestParameters.QUERY) String queries,
+                           @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                           @Context ServletContext context,
+                           @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleDeleteWithSystemID(httpServletRequest, context, systemId, queries, metadata);
     }
 }
--- a/services/system-network/src/main/java/com/redhat/thermostat/service/system/network/mongo/Fields.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * 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.service.system.network.mongo;
-
-class Fields {
-    static final String SYSTEM_ID = "systemId";
-    static final String SET = "set";
-    static final String LAST_UPDATED = "lastUpdated";
-    static final String RESPONSE = "response";
-}
--- a/services/system-network/src/main/java/com/redhat/thermostat/service/system/network/mongo/MongoStorageHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * 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.service.system.network.mongo;
-
-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;
-import org.bson.Document;
-import org.bson.conversions.Bson;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static com.mongodb.client.model.Filters.and;
-import static com.mongodb.client.model.Filters.eq;
-import static com.mongodb.client.model.Filters.or;
-import static com.mongodb.client.model.Projections.exclude;
-import static com.mongodb.client.model.Projections.excludeId;
-import static com.mongodb.client.model.Projections.fields;
-import static com.mongodb.client.model.Projections.include;
-
-public class MongoStorageHandler {
-
-    private final MongoResponseBuilder.Builder mongoResponseBuilder = new MongoResponseBuilder.Builder();
-
-    public String getOne(MongoCollection<Document> collection, String systemId, Integer limit, Integer offset, String sort, String includes, String excludes) {
-        Bson query = eq(Fields.SYSTEM_ID, systemId);
-        FindIterable<Document> documents = collection.find(query);
-
-        documents = buildProjection(documents, includes, excludes);
-
-        final Bson sortObject = MongoSortFilters.createSortObject(sort);
-        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit + offset).cursorType(CursorType.NonTailable);
-
-        return mongoResponseBuilder.queryDocuments(documents).build();
-    }
-
-    private FindIterable<Document> buildProjection(FindIterable<Document> documents, String includes, String excludes) {
-        if (excludes != null) {
-            List<String> excludesList = Arrays.asList(excludes.split(","));
-            documents = documents.projection(fields(exclude(excludesList), excludeId()));
-        } else if (includes != null) {
-            List<String> includesList = Arrays.asList(includes.split(","));
-            documents = documents.projection(fields(include(includesList), excludeId()));
-        } else {
-            documents = documents.projection(excludeId());
-        }
-
-        return documents;
-    }
-
-    public void addMany(MongoCollection<DBObject> collection, String body, String systemId) {
-        if (body.length() > 0) {
-            List<DBObject> inputList = (List<DBObject>) JSON.parse(body);
-            for (DBObject o : inputList) {
-                o.put(Fields.SYSTEM_ID, systemId);
-            }
-            collection.insertMany(inputList);
-        }
-    }
-
-    public void addOne(MongoCollection<DBObject> collection, String body, String systemId) {
-        if (body.length() > 0) {
-            DBObject obj = (DBObject) JSON.parse(body);
-            obj.put(Fields.SYSTEM_ID, systemId);
-            collection.insertOne(obj);
-        }
-    }
-
-    public void delete(MongoCollection<Document> collection, String systemId) {
-        Bson query = eq(Fields.SYSTEM_ID, systemId);
-        deleteDocuments(collection, query);
-    }
-
-    private void deleteDocuments(MongoCollection<Document> collection, Bson query) {
-        collection.deleteMany(query);
-    }
-
-    public void updateOne(MongoCollection<Document> collection, String body, String systemId, String queries) {
-        Bson baseQuery = eq(Fields.SYSTEM_ID, systemId);
-
-        BasicDBObject inputObject = (BasicDBObject) JSON.parse(body);
-        BasicDBObject setObject = (BasicDBObject) inputObject.get(Fields.SET);
-        if (setObject.containsField(Fields.SYSTEM_ID)) {
-            throw new UnsupportedOperationException("Updating " +  Fields.SYSTEM_ID + " fields is not allowed");
-        }
-
-        final List<String> queriesList;
-        if (queries != null) {
-            queriesList = Arrays.asList(queries.split(","));
-        } else {
-            queriesList = Collections.emptyList();
-        }
-
-        final Bson fields = new Document("$set", setObject);
-
-        collection.updateMany(and(baseQuery, MongoRequestFilters.buildQueriesFilter(queriesList)), fields);
-    }
-}
--- a/services/systems/src/main/java/com/redhat/thermostat/service/systems/http/Parameters.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * 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.service.systems.http;
-
-class Parameters {
-    static final String SYSTEM_ID = "systemId";
-
-    static final String SORT = "sort";
-    static final String QUERY = "query";
-    static final String OFFSET = "offset";
-    static final String LIMIT = "limit";
-    static final String INCLUDE = "include";
-    static final String EXCLUDE = "exclude";
-
-    static final String TIMESTAMP = "timeStamp";
-    static final String ALIVE_ONLY = "aliveOnly";
-}
--- a/services/systems/src/main/java/com/redhat/thermostat/service/systems/http/SystemsHttpHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/services/systems/src/main/java/com/redhat/thermostat/service/systems/http/SystemsHttpHandler.java	Fri Jul 21 09:30:27 2017 -0400
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.service.systems.http;
 
 import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
@@ -50,104 +51,80 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
-
-import com.mongodb.DBObject;
-import com.redhat.thermostat.gateway.common.mongodb.ThermostatMongoStorage;
-import com.redhat.thermostat.gateway.common.mongodb.servlet.ServletContextConstants;
-import com.redhat.thermostat.service.systems.mongo.MongoStorageHandler;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
+import com.redhat.thermostat.gateway.common.mongodb.servlet.MongoHttpHandlerHelper;
 
 @Path("/")
 public class SystemsHttpHandler {
-    private final MongoStorageHandler mongoStorageHandler = new MongoStorageHandler();
     private final String collectionName = "system-info";
+    private final MongoHttpHandlerHelper serviceHelper = new MongoHttpHandlerHelper( collectionName );
 
     @GET
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getSystemInfoAll(@QueryParam(Parameters.LIMIT) @DefaultValue("1") Integer limit,
-                                  @QueryParam(Parameters.OFFSET) @DefaultValue("0") Integer offset,
-                                  @QueryParam(Parameters.SORT) String sort,
-                                  @QueryParam(Parameters.QUERY) String queries,
-                                  @QueryParam(Parameters.INCLUDE) String includes,
-                                  @QueryParam(Parameters.EXCLUDE) String excludes,
-                                  @Context ServletContext context
-    ) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            String message = mongoStorageHandler.getSystemInfos(storage.getDatabase().getCollection(collectionName), limit, offset, sort, queries, includes, excludes);
-            return Response.status(Response.Status.OK).entity(message).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response getSystemInfoAll(@QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit,
+                                     @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") Integer offset,
+                                     @QueryParam(RequestParameters.SORT) String sort,
+                                     @QueryParam(RequestParameters.QUERY) String queries,
+                                     @QueryParam(RequestParameters.INCLUDE) String includes,
+                                     @QueryParam(RequestParameters.EXCLUDE) String excludes,
+                                     @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                     @Context ServletContext context,
+                                     @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleGet(httpServletRequest, context, limit, offset, sort, queries, includes, excludes, metadata);
     }
 
     @GET
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response getSystemInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                  @QueryParam(Parameters.LIMIT) @DefaultValue("1") Integer limit,
-                                  @QueryParam(Parameters.OFFSET) @DefaultValue("0") Integer offset,
-                                  @QueryParam(Parameters.SORT) String sort,
-                                  @QueryParam(Parameters.INCLUDE) String includes,
-                                  @QueryParam(Parameters.EXCLUDE) String excludes,
-                                  @Context ServletContext context
-    ) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            String message = mongoStorageHandler.getSystemInfo(storage.getDatabase().getCollection(collectionName), systemId, limit, offset, sort, includes, excludes);
-            return Response.status(Response.Status.OK).entity(message).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response getSystemInfo(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                  @QueryParam(RequestParameters.LIMIT) @DefaultValue("1") Integer limit,
+                                  @QueryParam(RequestParameters.OFFSET) @DefaultValue("0") Integer offset,
+                                  @QueryParam(RequestParameters.SORT) String sort,
+                                  @QueryParam(RequestParameters.QUERY) String queries,
+                                  @QueryParam(RequestParameters.INCLUDE) String includes,
+                                  @QueryParam(RequestParameters.EXCLUDE) String excludes,
+                                  @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                  @Context ServletContext context,
+                                  @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleGetWithSystemID(httpServletRequest, context, systemId, limit, offset, sort, queries, includes, excludes, metadata);
     }
 
     @PUT
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response putSystemInfo(String body,
-                                  @PathParam(Parameters.SYSTEM_ID) String systemId,
-                                  @QueryParam(Parameters.QUERY) String queries,
-                                  @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.updateSystemInfo(storage.getDatabase().getCollection(collectionName), body, systemId, queries);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                                  @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                  @QueryParam(RequestParameters.QUERY) String queries,
+                                  @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                  @Context ServletContext context,
+                                  @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePutWithSystemId(httpServletRequest, context, systemId, queries, metadata, body);
     }
 
     @POST
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
     public Response postSystemInfo(String body,
-                                   @PathParam(Parameters.SYSTEM_ID) String systemId,
-                                   @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.addSystemInfos(storage.getDatabase().getCollection(collectionName, DBObject.class), body, systemId);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+                                   @PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                   @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                   @Context ServletContext context,
+                                   @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handlePostWithSystemID(httpServletRequest, context, systemId, metadata, body);
     }
 
     @DELETE
-    @Path("/systems/{" + Parameters.SYSTEM_ID +"}")
+    @Path("/systems/{" + RequestParameters.SYSTEM_ID +"}")
     @Consumes({ "application/json" })
     @Produces({ "application/json", "text/html; charset=utf-8" })
-    public Response deleteSystemInfo(@PathParam(Parameters.SYSTEM_ID) String systemId,
-                                     @QueryParam(Parameters.QUERY) String queries,
-                                     @Context ServletContext context) {
-        try {
-            ThermostatMongoStorage storage = (ThermostatMongoStorage) context.getAttribute(ServletContextConstants.MONGODB_CLIENT_ATTRIBUTE);
-            mongoStorageHandler.deleteSystemInfo(storage.getDatabase().getCollection(collectionName), systemId);
-            return Response.status(Response.Status.OK).build();
-        } catch (Exception e) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
+    public Response deleteSystemInfo(@PathParam(RequestParameters.SYSTEM_ID) String systemId,
+                                     @QueryParam(RequestParameters.QUERY) String queries,
+                                     @QueryParam(RequestParameters.METADATA) @DefaultValue("false") String metadata,
+                                     @Context ServletContext context,
+                                     @Context HttpServletRequest httpServletRequest) {
+        return serviceHelper.handleDeleteWithSystemID(httpServletRequest, context, systemId, queries, metadata);
     }
 }
--- a/services/systems/src/main/java/com/redhat/thermostat/service/systems/mongo/Fields.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * 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.service.systems.mongo;
-
-class Fields {
-    static final String SYSTEM_ID = "systemId";
-
-    static final String SET = "set";
-    static final String LAST_UPDATED = "lastUpdated";
-    static final String STOP_TIME = "stopTime";
-
-    static final String RESPONSE = "response";
-    static final String SYSTEMS = "systems";
-}
--- a/services/systems/src/main/java/com/redhat/thermostat/service/systems/mongo/MongoStorageHandler.java	Fri Jul 21 08:30:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * 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.service.systems.mongo;
-
-import static com.mongodb.client.model.Filters.and;
-import static com.mongodb.client.model.Filters.eq;
-import static com.mongodb.client.model.Projections.exclude;
-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 MongoStorageHandler {
-
-    private final MongoResponseBuilder.Builder mongoResponseBuilder = new MongoResponseBuilder.Builder();
-
-    public String getSystemInfos(MongoCollection<Document> collection, Integer limit, Integer offset, String sort, String queries, String includes, String excludes) {
-        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();
-        }
-
-        documents = buildProjection(documents, includes, excludes);
-
-        final Bson sortObject = MongoSortFilters.createSortObject(sort);
-        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit).cursorType(CursorType.NonTailable);
-
-        return mongoResponseBuilder.queryDocuments(documents).build();
-    }
-
-    public String getSystemInfo(MongoCollection<Document> collection, String systemId, Integer limit, Integer offset, String sort, String includes, String excludes) {
-        Bson query = eq(Fields.SYSTEM_ID, systemId);
-        FindIterable<Document> documents = collection.find(query);
-
-        documents = buildProjection(documents, includes, excludes);
-
-        final Bson sortObject = MongoSortFilters.createSortObject(sort);
-        documents = documents.sort(sortObject).limit(limit).skip(offset).batchSize(limit + offset).cursorType(CursorType.NonTailable);
-
-        return mongoResponseBuilder.queryDocuments(documents).build();
-    }
-
-    private FindIterable<Document> buildProjection(FindIterable<Document> documents, String includes, String excludes) {
-        if (excludes != null) {
-            List<String> excludesList = Arrays.asList(excludes.split(","));
-            documents = documents.projection(fields(exclude(excludesList), excludeId()));
-        } else if (includes != null) {
-            List<String> includesList = Arrays.asList(includes.split(","));
-            documents = documents.projection(fields(include(includesList), excludeId()));
-        } else {
-            documents = documents.projection(excludeId());
-        }
-
-        return documents;
-    }
-
-    public void addSystemInfos(MongoCollection<DBObject> collection, String body, String systemId) {
-        if (body.length() > 0) {
-            List<DBObject> inputList = (List<DBObject>) JSON.parse(body);
-            for (DBObject o : inputList) {
-                o.put(Fields.SYSTEM_ID, systemId);
-            }
-            collection.insertMany(inputList);
-        }
-    }
-
-    public void deleteSystemInfo(MongoCollection<Document> collection, String systemId) {
-        Bson query = eq(Fields.SYSTEM_ID, systemId);
-        deleteDocuments(collection, query);
-    }
-
-    private void deleteDocuments(MongoCollection<Document> collection, Bson query) {
-        collection.deleteMany(query);
-    }
-
-    public void updateSystemInfo(MongoCollection<Document> collection, String body, String systemId, String queries) {
-        Bson baseQuery = eq(Fields.SYSTEM_ID, systemId);
-
-        BasicDBObject inputObject = (BasicDBObject) JSON.parse(body);
-        BasicDBObject setObject = (BasicDBObject) inputObject.get(Fields.SET);
-        if (setObject.containsField(Fields.SYSTEM_ID)) {
-            throw new UnsupportedOperationException("Updating " +  Fields.SYSTEM_ID + " fields is not allowed");
-        }
-
-        final List<String> queriesList;
-        if (queries != null) {
-            queriesList = Arrays.asList(queries.split(","));
-        } else {
-            queriesList = Collections.emptyList();
-        }
-
-        final Bson fields = new Document("$set", setObject);
-
-        collection.updateMany(and(baseQuery, MongoRequestFilters.buildQueriesFilter(queriesList)), fields);
-    }
-}
--- a/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/gc/JvmGcServiceIntegrationTest.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/gc/JvmGcServiceIntegrationTest.java	Fri Jul 21 09:30:27 2017 -0400
@@ -46,6 +46,8 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
+import com.redhat.thermostat.gateway.common.mongodb.servlet.RequestParameters;
+import com.redhat.thermostat.gateway.tests.integration.MongoIntegrationTest;
 import org.bson.Document;
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.util.StringContentProvider;
@@ -58,7 +60,6 @@
 import com.mongodb.Block;
 import com.mongodb.client.FindIterable;
 import com.mongodb.client.MongoCollection;
-import com.redhat.thermostat.gateway.tests.integration.MongoIntegrationTest;
 
 public class JvmGcServiceIntegrationTest extends MongoIntegrationTest {
 
@@ -68,6 +69,14 @@
     private final String data = "[{ \"a\" : \"test\", \"b\" : \"test1\", \"c\" : \"test2\" }, { \"d\" : \"test3\"}," +
             "{\"e\" : \"test4\" }]";
 
+    private static final String QUERY_PREFIX = "query";
+    private static final String LIMIT_PREFIX = "limit";
+    private static final String SORT_PREFIX = "sort";
+    private static final String OFFSET_PREFIX = "offset";
+    private static final String METADATA_PREFIX = "metadata";
+    private static final String INCLUDE_PREFIX = "include";
+    private static final String IEXCLUDE_PREFIX = "exclude";
+
     public JvmGcServiceIntegrationTest() {
         super(serviceName + "/" + versionNumber, serviceName);
     }
@@ -108,7 +117,7 @@
     @Test
     public void testGetLimitParam() throws InterruptedException, TimeoutException, ExecutionException {
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?l=2","{\"response\":[{\"a\":\"test\",\"b\":"+
+        makeHttpGetRequest(gcUrl + '?' + LIMIT_PREFIX + "=2","{\"response\":[{\"a\":\"test\",\"b\":"+
                 "\"test1\",\"c\":\"test2\"},{\"d\":\"test3\"}]}", 200);
     }
 
@@ -117,33 +126,33 @@
         String data ="[{\"a\":\"1\"}, {\"a\":\"2\"}]";
 
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?l=3&s=-a","{\"response\":[{\"a\":\"2\"},{\"a\":"+
+        makeHttpGetRequest(gcUrl + '?' + LIMIT_PREFIX + "=2&" + SORT_PREFIX + "=-a","{\"response\":[{\"a\":\"2\"},{\"a\":"+
                 "\"1\"}]}", 200);
     }
 
     @Test
     public void testGetProjectParam() throws InterruptedException, TimeoutException, ExecutionException {
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?p=b,c","{\"response\":[{\"b\":\"test1\",\"c\":"+
+        makeHttpGetRequest(gcUrl + '?' + INCLUDE_PREFIX + "=b,c","{\"response\":[{\"b\":\"test1\",\"c\":"+
                 "\"test2\"}]}", 200);
     }
 
     @Test
     public void testGetOffsetParam() throws InterruptedException, TimeoutException, ExecutionException {
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?o=1","{\"response\":[{\"d\":\"test3\"}]}", 200);
+        makeHttpGetRequest(gcUrl + '?' + OFFSET_PREFIX + "=1","{\"response\":[{\"d\":\"test3\"}]}", 200);
     }
 
     @Test
     public void testGetQueryParam() throws InterruptedException, TimeoutException, ExecutionException {
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1","{\"response\":[{\"a\":\"test\",\"b\":"+
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1","{\"response\":[{\"a\":\"test\",\"b\":"+
                 "\"test1\",\"c\":\"test2\"}]}", 200);
     }
 
     @Test
     public void testPostJSON() throws InterruptedException, TimeoutException, ExecutionException {
-        makeHttpMethodRequest(HttpMethod.POST,"?m=true","[{\"f1\":\"test\"}]","application/json",
+        makeHttpMethodRequest(HttpMethod.POST, '?' + METADATA_PREFIX + "=true","[{\"f1\":\"test\"}]","application/json",
                 "{\"response\":[{\"f1\":\"test\"}]}", 200);
     }
 
@@ -165,7 +174,7 @@
 
     @Test
     public void testNonExistentDataDelete() throws InterruptedException, TimeoutException, ExecutionException {
-        makeHttpMethodRequest(HttpMethod.DELETE,"?q=nonExist==Null","","","", 200);
+        makeHttpMethodRequest(HttpMethod.DELETE,'?' + QUERY_PREFIX + "=nonExist==Null","","","", 200);
     }
 
     @Test
@@ -173,7 +182,7 @@
         makeHttpMethodRequest(HttpMethod.POST,"","[{\"f1\":\"test\"}]","application/json",
                 "{\"response\":[{\"f1\":\"test\"}]}", 200);
 
-        makeHttpMethodRequest(HttpMethod.PUT,"?q=f1==test","{\"set\": {\"f1\":\"newdata\"}}",
+        makeHttpMethodRequest(HttpMethod.PUT,'?' + QUERY_PREFIX + "=f1==test","{\"set\": {\"f1\":\"newdata\"}}",
                 "application/json","{\"response\":[{\"f1\":\"newdata\"}]}", 200);
 
         makeHttpMethodRequest(HttpMethod.DELETE,"?q=f1==test","","","", 200);
@@ -189,10 +198,10 @@
         //"next":"http://127.0.0.1:30000/jvm-gc/0.0.2?o=1&l=1&q===test1&m=true"}}
         String expectedResponse ="{\"response\":[{\"a\":\"test\",\"b\":\"test1\",\"c\":\"test2\"}],"+
                 "\"metaData\":{\"payloadCount\":1,\"count\":3,"+
-                "\"next\":\"" + gcUrl + "?o\\u003d1\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"next\":\"" + gcUrl + "?" + OFFSET_PREFIX + "\\u003d1\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX  +"\\u003dtrue\"}}";
 
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1&m=true&l=1", expectedResponse, 200);
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=1", expectedResponse, 200);
     }
 
     @Test
@@ -205,11 +214,11 @@
         //"next":"http://127.0.0.1:30000/jvm-gc/0.0.2?o=2&l=1&q===test1&m=true"}}
         String expectedResponse ="{\"response\":[{\"b\":\"test1\"}],"+
                 "\"metaData\":{\"payloadCount\":1,\"count\":3,"+
-                "\"prev\":\"" + gcUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d1\","+
-                "\"next\":\"" + gcUrl + "?o\\u003d2\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + gcUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d1\","+
+                "\"next\":\"" + gcUrl + "?" + OFFSET_PREFIX + "\\u003d2\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1&m=true&o=1", expectedResponse, 200);
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=1", expectedResponse, 200);
     }
 
     @Test
@@ -223,11 +232,11 @@
         //"next":"http://127.0.0.1:30000/jvm-gc/0.0.2?o=5&l=1&q===test1&m=true"}}
         String expectedResponse ="{\"response\":[{\"b\":\"test1\"},{\"b\":\"test1\"}],"+
                 "\"metaData\":{\"payloadCount\":1,\"count\":6,"+
-                "\"prev\":\"" + gcUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d1\","+
-                "\"next\":\"" + gcUrl + "?o\\u003d5\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + gcUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d1\","+
+                "\"next\":\"" + gcUrl + "?" + OFFSET_PREFIX + "\\u003d5\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1&m=true&o=3&l=2", expectedResponse, 200);
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=2&" + OFFSET_PREFIX + "=3", expectedResponse, 200);
     }
 
     @Test
@@ -240,11 +249,11 @@
         //"next":"http://127.0.0.1:30000/jvm-gc/0.0.2?o=2&l=1&q===test1&m=true"}}
         String expectedResponse ="{\"response\":[{\"b\":\"test1\"}],"+
                 "\"metaData\":{\"payloadCount\":1,\"count\":3,"+
-                "\"prev\":\"" + gcUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d1\","+
-                "\"next\":\"" + gcUrl + "?o\\u003d2\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + gcUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d1\","+
+                "\"next\":\"" + gcUrl + "?" + OFFSET_PREFIX + "\\u003d2\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1&m=true&o=1&l=1", expectedResponse, 200);
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=1&" + OFFSET_PREFIX + "=1", expectedResponse, 200);
     }
 
     @Test
@@ -258,11 +267,11 @@
         //"next":"http://127.0.0.1:30000/jvm-gc/0.0.2?o=3&l=2&q===test1&m=true"}}
         String expectedResponse ="{\"response\":[{\"b\":\"test1\"},{\"e\":\"test4\",\"b\":\"test1\"}],"+
                 "\"metaData\":{\"payloadCount\":2,\"count\":6,"+
-                "\"prev\":\"" + gcUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d1\\u0026o\\u003d0\","+
-                "\"next\":\"" + gcUrl + "?o\\u003d3\\u0026l\\u003d2\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + gcUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + OFFSET_PREFIX + "\\u003d0\","+
+                "\"next\":\"" + gcUrl + "?" + OFFSET_PREFIX + "\\u003d3\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1&m=true&o=1&l=2", expectedResponse, 200);
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=2&" + OFFSET_PREFIX + "=1", expectedResponse, 200);
     }
 
     @Test
@@ -277,11 +286,11 @@
         //"next":"http://127.0.0.1:30000/jvm-gc/0.0.2?o=5&l=1&q===test1&m=true"}}
         String expectedResponse ="{\"response\":[{\"b\":\"test1\"},{\"b\":\"test1\"}],"+
                 "\"metaData\":{\"payloadCount\":1,\"count\":6,"+
-                "\"prev\":\"" + gcUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d1\","+
-                "\"next\":\"" + gcUrl + "?o\\u003d5\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + gcUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d1\","+
+                "\"next\":\"" + gcUrl + "?" + OFFSET_PREFIX + "\\u003d5\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1&m=true&o=3&l=2", expectedResponse, 200);
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=2&" + OFFSET_PREFIX + "=3", expectedResponse, 200);
     }
 
     @Test
@@ -295,11 +304,11 @@
         //"next":"http://127.0.0.1:30000/jvm-gc/0.0.2?o=4&l=2&q===test1&m=true"}}
         String expectedResponse ="{\"response\":[{\"e\":\"test4\",\"b\":\"test1\"},{\"b\":\"test1\"}],"+
                 "\"metaData\":{\"payloadCount\":2,\"count\":6,"+
-                "\"prev\":\"" + gcUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d0\","+
-                "\"next\":\"" + gcUrl + "?o\\u003d4\\u0026l\\u003d2\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + gcUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d0\","+
+                "\"next\":\"" + gcUrl + "?" + OFFSET_PREFIX + "\\u003d4\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1&m=true&o=2&l=2", expectedResponse, 200);
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=2&" + OFFSET_PREFIX + "=2", expectedResponse, 200);
     }
 
     @Test
@@ -314,10 +323,10 @@
         //"next":"http://127.0.0.1:30000/jvm-gc/0.0.2?o=4&l=2&q===test1&m=true"}}
         String expectedResponse ="{\"response\":[{\"e\":\"test4\",\"b\":\"test1\"},{\"b\":\"test1\"}],"+
                 "\"metaData\":{\"payloadCount\":2,\"count\":6,"+
-                "\"prev\":\"" + gcUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d0\","+
-                "\"next\":\"" + gcUrl + "?o\\u003d4\\u0026l\\u003d2\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + gcUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d0\","+
+            "\"next\":\"" + gcUrl + "?" + OFFSET_PREFIX + "\\u003d4\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1&m=true&o=2&l=2", expectedResponse, 200);
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=2&" + OFFSET_PREFIX + "=2", expectedResponse, 200);
     }
 
     @Test
@@ -333,10 +342,10 @@
         String expectedResponse ="{\"response\":[{\"e\":\"test4\",\"b\":\"test1\"},"+
                 "{\"b\":\"test1\"},{\"b\":\"test1\"}],"+
                 "\"metaData\":{\"payloadCount\":1,\"count\":6,"+
-                "\"prev\":\"" + gcUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d0\","+
-                "\"next\":\"" + gcUrl + "?o\\u003d5\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + gcUrl + "?" +QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d0\","+
+                "\"next\":\"" + gcUrl + "?" + OFFSET_PREFIX + "\\u003d5\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
         makeHttpMethodRequest(HttpMethod.POST,"", data,"application/json","", 200);
-        makeHttpGetRequest(gcUrl +"?q=b==test1&m=true&o=2&l=3", expectedResponse, 200);
+        makeHttpGetRequest(gcUrl + '?' + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=3&" + OFFSET_PREFIX + "=2", expectedResponse, 200);
     }
 
     @Test
@@ -398,7 +407,7 @@
 
         String updateString = "{\"set\" : {\"item\" : 5}}";
         StringContentProvider stringContentProvider = new StringContentProvider(updateString, "UTF-8");
-        ContentResponse response = client.newRequest(gcUrl).param("q", "realms==[\"a\"]")
+        ContentResponse response = client.newRequest(gcUrl).param(RequestParameters.QUERY, "realms==[\"a\"]")
                 .method(HttpMethod.PUT).content(stringContentProvider, "application/json")
                 .send();
         assertEquals(400, response.getStatus());
@@ -466,7 +475,7 @@
 
         String expected = "{\"response\":[{\"item\":1.0}]}";
 
-        makeHttpGetRequest(gcUrl + "?p=realms,item",expected, 200);
+        makeHttpGetRequest(gcUrl + "?" + RequestParameters.INCLUDE + "=realms,item",expected, 200);
     }
 
     @Test
@@ -481,7 +490,7 @@
         collection.insertMany(insertDocuments);
 
         ContentResponse response = client.newRequest(gcUrl)
-                .param("q", "realms==[\"a\"]").method(HttpMethod.GET).send();
+                .param(RequestParameters.QUERY, "realms==[\"a\"]").method(HttpMethod.GET).send();
 
         assertEquals(400, response.getStatus());
     }
@@ -517,7 +526,7 @@
         collection.insertMany(insertDocuments);
 
         ContentResponse response = client.newRequest(gcUrl)
-                .param("q", "realms==[\"a\",\"b\"]").method(HttpMethod.DELETE)
+                .param(RequestParameters.QUERY, "realms==[\"a\",\"b\"]").method(HttpMethod.DELETE)
                 .send();
         assertEquals(400, response.getStatus());
 
--- a/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/memory/JvmMemoryServiceIntegrationTest.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvm/memory/JvmMemoryServiceIntegrationTest.java	Fri Jul 21 09:30:27 2017 -0400
@@ -36,23 +36,31 @@
 
 package com.redhat.thermostat.gateway.service.jvm.memory;
 
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
+import com.redhat.thermostat.gateway.tests.integration.MongoIntegrationTest;
+import com.redhat.thermostat.gateway.tests.utils.HttpTestUtil;
 import org.eclipse.jetty.http.HttpMethod;
 import org.junit.Test;
 
-import com.redhat.thermostat.gateway.tests.integration.MongoIntegrationTest;
-import com.redhat.thermostat.gateway.tests.utils.HttpTestUtil;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
 
 public class JvmMemoryServiceIntegrationTest extends MongoIntegrationTest {
 
     private static final String serviceName = "jvm-memory";
     private static final String versionNumber = "0.0.2";
-    private static final String memoryUrl = baseUrl + "/" + serviceName + "/" + versionNumber;
+
+    private static final String QUERY_PREFIX = "query";
+    private static final String LIMIT_PREFIX = "limit";
+    private static final String SORT_PREFIX = "sort";
+    private static final String OFFSET_PREFIX = "offset";
+    private static final String METADATA_PREFIX = "metadata";
+    private static final String INCLUDE_PREFIX = "include";
+
+    private final String returnedUrl;
 
     public JvmMemoryServiceIntegrationTest() {
         super(serviceName + "/" + versionNumber, serviceName);
+        this.returnedUrl = resourceUrl;
     }
 
     @Test
@@ -72,11 +80,11 @@
         String expectedFirst = "{\"response\":[{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"}]}";
         String expectedAll = "{\"response\":[{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"},{\"x\":\"y\"},{\"z\":\"z\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"},{\"x\":\"y\"},{\"z\":\"z\"}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=5", 200, expectedAll);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=a==b", 200, expectedFirst);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=c==d", 200, expectedFirst);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=a==b,c==d", 200, expectedFirst);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=a==b,c==none", 200, HttpTestUtil.EMPTY_RESPONSE);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedAll);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=a==b", 200, expectedFirst);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=c==d", 200, expectedFirst);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=a==b,c==d", 200, expectedFirst);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=a==b,c==none", 200, HttpTestUtil.EMPTY_RESPONSE);
     }
 
     @Test
@@ -84,11 +92,11 @@
         String expectedAll = "{\"response\":[{\"a\":\"b\"},{\"c\":\"d\"}]}";
         String expectedAmpersand = "{\"response\":[{\"a\":\"b\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"b\"},{\"c\":\"d\"}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=5", 200, expectedAll);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedAll);
 
         // Since q=a==b&c==d means "q= 'a==b'" and "c= '=d'", we should only
         // get 'a: b' back.
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=a==b&c==d", 200, expectedAmpersand);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=a==b&c==d", 200, expectedAmpersand);
 
         // The following should find the one with multiple matches, not the
         // single match. This means we will evaluate u==v only, and should get
@@ -96,8 +104,8 @@
         String expectedSingleMatch = "{\"response\":[{\"u\":\"v\",\"x\":\"y\"}]}";
         String expectedMultiMatch = "{\"response\":[{\"u\":\"v\",\"x\":\"y\"},{\"u\":\"v\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"x\":\"y\"},{\"u\":\"v\",\"x\":\"y\"},{\"u\":\"v\"}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=u==v&q=x==y", 200, expectedSingleMatch);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=u==v&q=x==y&l=5", 200, expectedMultiMatch);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=u==v&" + QUERY_PREFIX + "=x==y", 200, expectedSingleMatch);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=u==v&" + QUERY_PREFIX + "=x==y&" + LIMIT_PREFIX + "=5", 200, expectedMultiMatch);
     }
 
     @Test
@@ -105,7 +113,7 @@
         String expectedResponse = "{\"response\":[{\"fakedata\":\"test\"},{\"new\":\"data\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"fakedata\":\"test\"}]");
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"new\":\"data\"}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=5", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedResponse);
     }
 
     @Test
@@ -114,7 +122,7 @@
         String expectedDataAfterPut = "{\"response\":[{\"a\":\"b\",\"x\":\"y\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"b\"},{\"a\":\"c\"}]");
         HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl, 200, expectedDataBeforePut);
-        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?q=a==b", "{\"set\":{\"x\":\"y\"}}", 200);
+        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?" + QUERY_PREFIX + "=a==b", "{\"set\":{\"x\":\"y\"}}", 200);
         HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl, 200, expectedDataAfterPut);
     }
 
@@ -125,20 +133,20 @@
         String expectedAllDataAfterPut = "{\"response\":[{\"a\":\"c\"},{\"x\":\"y\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"b\"},{\"x\":\"y\"}]");
         HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl, 200, expectedDataBeforePut);
-        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?q=a==b", "{\"set\":{\"a\":\"c\"}}", 200);
+        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?" + QUERY_PREFIX + "=a==b", "{\"set\":{\"a\":\"c\"}}", 200);
         HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl, 200, expectedDataAfterPut);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=5", 200, expectedAllDataAfterPut);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedAllDataAfterPut);
     }
 
     @Test
     public void testDeleteProperlyDeletesData() throws InterruptedException, TimeoutException, ExecutionException {
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"fakedata\":\"test\"}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.DELETE, resourceUrl + "?q=fakedata==test", 200);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.DELETE, resourceUrl + "?" + QUERY_PREFIX + "=fakedata==test", 200);
         HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl, 200, HttpTestUtil.EMPTY_RESPONSE);
 
         String expectedAfterDeletion = "{\"response\":[{\"c\":\"d\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"fakedata\":\"test\",\"a\":\"b\"},{\"c\":\"d\"}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.DELETE, resourceUrl + "?q=a==b", 200);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.DELETE, resourceUrl + "?" + QUERY_PREFIX + "=a==b", 200);
         HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl, 200, expectedAfterDeletion);
     }
 
@@ -147,7 +155,7 @@
         String expectedDataResponse = "{\"response\":[{\"fakedata\":\"test\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"fakedata\":\"test\"}]");
         HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl, 200, expectedDataResponse);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.DELETE, resourceUrl + "?q=nosuchkey==", 200);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.DELETE, resourceUrl + "?" + QUERY_PREFIX + "=nosuchkey==", 200);
         HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl, 200, expectedDataResponse);
     }
 
@@ -160,10 +168,10 @@
     @Test
     public void testPostAndPutWithInvalidData() throws InterruptedException, TimeoutException, ExecutionException {
         String expectedDataResponse = "{\"response\":[{\"fakedata\":\"test\"}]}";
-        String urlQuery = resourceUrl + "?q=nosuchkey==nosuchvalue";
+        String urlQuery = resourceUrl + "?" + QUERY_PREFIX + "=nosuchkey==nosuchvalue";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"fakedata\":\"test\"}]");
         HttpTestUtil.testContentResponse(client, HttpMethod.PUT, urlQuery, "{\"set\":{\"fakedata\":\"somethingnew\"}}", 200);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=5", 200, expectedDataResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedDataResponse);
     }
 
     @Test
@@ -171,33 +179,33 @@
         String expectedDataResponse = "{\"response\":[{\"fakedata\":\"test\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"fakedata\":\"test\"}]");
         HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl, "{\"set\":{\"fakedata\":\"test\"}}", 200);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=5", 200, expectedDataResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedDataResponse);
     }
 
     @Test
     public void testPutDifferentData() throws InterruptedException, TimeoutException, ExecutionException {
         String expectedDataResponse = "{\"response\":[{\"a\":\"b\",\"c\":\"d\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"b\"}]");
-        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?q=a==b", "{\"set\":{\"c\":\"d\"}}", 200);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=5", 200, expectedDataResponse);
+        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?" + QUERY_PREFIX + "=a==b", "{\"set\":{\"c\":\"d\"}}", 200);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedDataResponse);
     }
 
     @Test
     public void testChangeDataWithPutMultipleTimes() throws InterruptedException, TimeoutException, ExecutionException {
         String expectedData = "{\"response\":[{\"a\":\"a2\",\"b\":\"b2\",\"c\":\"c2\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"a2\"}]");
-        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?q=a==a2", "{\"set\":{\"b\":\"b2\"}}", 200);
-        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?q=a==a2", "{\"set\":{\"c\":\"c2\"}}", 200);
+        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?" + QUERY_PREFIX + "=a==a2", "{\"set\":{\"b\":\"b2\"}}", 200);
+        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?" + QUERY_PREFIX + "=a==a2", "{\"set\":{\"c\":\"c2\"}}", 200);
 
         // It won't find the target from the query, so the addition should not occur to any object.
-        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?q=a==none", "{\"set\":{\"d\":\"d2\"}}", 200);
+        HttpTestUtil.testContentResponse(client, HttpMethod.PUT, resourceUrl + "?" + QUERY_PREFIX + "=a==none", "{\"set\":{\"d\":\"d2\"}}", 200);
 
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=5", 200, expectedData);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=5", 200, expectedData);
     }
 
     @Test
     public void testGetWithBadUrlQuery() throws InterruptedException, TimeoutException, ExecutionException {
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=2", 400);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=2", 400);
     }
 
     @Test
@@ -206,23 +214,23 @@
         String expectedDataAll = "{\"response\":[{\"a\":\"a2\"},{\"b\":\"b2\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"a2\"},{\"b\":\"b2\"}]");
         HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl, 200, expectedDataOne);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=2", 200, expectedDataAll);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=2", 200, expectedDataAll);
     }
 
     @Test
     public void testQueryOffset() throws InterruptedException, TimeoutException, ExecutionException {
         String expectedOffsetRestOfData = "{\"response\":[{\"b\":\"2\"},{\"c\":\"3\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"1\"},{\"b\":\"2\"},{\"c\":\"3\"}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?o=1", 200, "{\"response\":[{\"b\":\"2\"}]}");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?o=3", 200, HttpTestUtil.EMPTY_RESPONSE);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=5&o=1", 200, expectedOffsetRestOfData);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + OFFSET_PREFIX + "=1", 200, "{\"response\":[{\"b\":\"2\"}]}");
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + OFFSET_PREFIX + "=3", 200, HttpTestUtil.EMPTY_RESPONSE);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=5&" + OFFSET_PREFIX + "=1", 200, expectedOffsetRestOfData);
     }
 
     @Test
     public void testNegativeOffsetQuery() throws InterruptedException, TimeoutException, ExecutionException {
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"1\"}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?o=-1", 400);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?o=-582", 400);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + OFFSET_PREFIX + "=-1", 400);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + OFFSET_PREFIX + "=-582", 400);
     }
 
     @Test
@@ -230,15 +238,15 @@
         String expectedGet = "{\"response\":[{\"a\":1},{\"a\":2}]}";
         String expectedGetReverse = "{\"response\":[{\"a\":2},{\"a\":1}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":1},{\"a\":2}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=10&s=+a", 200, expectedGet);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?l=10&s=-a", 200, expectedGetReverse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=10&" + SORT_PREFIX + "=+a", 200, expectedGet);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + LIMIT_PREFIX + "=10&" + SORT_PREFIX + "=-a", 200, expectedGetReverse);
     }
 
     @Test
     public void testQueryProjection() throws InterruptedException, TimeoutException, ExecutionException {
         String expectedGet = "{\"response\":[{\"b\":\"2\",\"c\":\"3\"}]}";
         HttpTestUtil.addRecords(client, resourceUrl, "[{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"}]");
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?p=b,c", 200, expectedGet);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + INCLUDE_PREFIX + "=b,c", 200, expectedGet);
     }
 
     @Test
@@ -251,10 +259,10 @@
         // "next":"http://127.0.0.1:30000/jvm-memory/0.0.2?o=1&l=1&q===test1&m=true"}}
         String expectedResponse = "{\"response\":[{\"a\":\"test\",\"b\":\"test1\"," +
                 "\"c\":\"test2\"}],\"metaData\":{\"payloadCount\":1,\"count\":3," +
-                "\"next\":\"" + memoryUrl + "?o\\u003d1\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d1\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&l=1", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + LIMIT_PREFIX + "=1", 200, expectedResponse);
     }
 
     @Test
@@ -267,11 +275,11 @@
         // "next":"http://127.0.0.1:30000/jvm-memory/0.0.2?o=2&l=1&q===test1&m=true"}}
         String expectedResponse = "{\"response\":[{\"b\":\"test1\"}]," +
                 "\"metaData\":{\"payloadCount\":1,\"count\":3," +
-                "\"prev\":\"" + memoryUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d1\"," +
-                "\"next\":\"" + memoryUrl + "?o\\u003d2\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d1\"," +
+                "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d2\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&o=1", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=1", 200, expectedResponse);
     }
 
     @Test
@@ -286,12 +294,12 @@
         String expectedResponse = "{\"response\":[{\"b\":\"test1\"},{\"e\":\"test4\"," +
                 "\"b\":\"test1\"},{\"b\":\"test1\"}]," +
                 "\"metaData\":{\"payloadCount\":1,\"count\":5," +
-                "\"prev\":\"" + memoryUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue" +
-                "\\u0026l\\u003d1\\u0026o\\u003d0\",\"next\":\"" + memoryUrl + "?o\\u003d4" +
-                "\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue" +
+                "\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + OFFSET_PREFIX + "\\u003d0\",\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d4" +
+                "\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&o=1&l=3", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=1&" + LIMIT_PREFIX + "=3", 200, expectedResponse);
     }
 
     @Test
@@ -306,11 +314,11 @@
         // "next":"http://127.0.0.1:30000/jvm-memory/0.0.2?o=5&l=1&q===test1&m=true"}}
         String expectedResponse = "{\"response\":[{\"b\":\"test1\"},{\"b\":\"test1\"}]," +
                 "\"metaData\":{\"payloadCount\":1,\"count\":6," +
-                "\"prev\":\"" + memoryUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d1\"," +
-                "\"next\":\"" + memoryUrl + "?o\\u003d5\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d1\"," +
+                "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d5\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&o=3&l=2", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=3&" + LIMIT_PREFIX + "=2", 200, expectedResponse);
     }
 
     @Test
@@ -324,11 +332,11 @@
         // "next":"http://127.0.0.1:30000/jvm-memory/0.0.2?o=2&l=1&q===test1&m=true"}}
         String expectedResponse = "{\"response\":[{\"b\":\"test1\"}]," +
                 "\"metaData\":{\"payloadCount\":1,\"count\":3," +
-                "\"prev\":\"" + memoryUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d1\"," +
-                "\"next\":\"" + memoryUrl + "?o\\u003d2\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d1\"," +
+                "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d2\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&o=1&l=1", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=1&" + LIMIT_PREFIX + "=1", 200, expectedResponse);
     }
 
     @Test
@@ -343,11 +351,11 @@
         // "next":"http://127.0.0.1:30000/jvm-memory/0.0.2?o=3&l=2&q===test1&m=true"}}
         String expectedResponse = "{\"response\":[{\"b\":\"test1\"},{\"e\":\"test4\"," +
                 "\"b\":\"test1\"}],\"metaData\":{\"payloadCount\":2,\"count\":6," +
-                "\"prev\":\"" + memoryUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d1\\u0026o\\u003d0\"," +
-                "\"next\":\"" + memoryUrl + "?o\\u003d3\\u0026l\\u003d2\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + OFFSET_PREFIX + "\\u003d0\"," +
+                "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d3\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&o=1&l=2", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=1&" + LIMIT_PREFIX + "=2", 200, expectedResponse);
     }
 
     @Test
@@ -362,11 +370,11 @@
         // "next":"http://127.0.0.1:30000/jvm-memory/0.0.2?o=5&l=1&q===test1&m=true"}}
         String expectedResponse = "{\"response\":[{\"b\":\"test1\"},{\"b\":\"test1\"}]," +
                 "\"metaData\":{\"payloadCount\":1,\"count\":6," +
-                "\"prev\":\"" + memoryUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d1\"," +
-                "\"next\":\"" + memoryUrl + "?o\\u003d5\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d1\"," +
+                "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d5\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&o=3&l=2", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=3&" +LIMIT_PREFIX + "=2", 200, expectedResponse);
     }
 
     @Test
@@ -380,11 +388,11 @@
         // "next":"http://127.0.0.1:30000/jvm-memory/0.0.2?o=4&l=2&q===test1&m=true"}}
         String expectedResponse = "{\"response\":[{\"e\":\"test4\",\"b\":\"test1\"},{\"b\":\"test1\"}]," +
                 "\"metaData\":{\"payloadCount\":2,\"count\":6," +
-                "\"prev\":\"" + memoryUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d0\"," +
-                "\"next\":\"" + memoryUrl + "?o\\u003d4\\u0026l\\u003d2\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d0\"," +
+                "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d4\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&o=2&l=2", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=2&" + LIMIT_PREFIX + "=2", 200, expectedResponse);
     }
 
     @Test
@@ -399,11 +407,11 @@
         // "next":"http://127.0.0.1:30000/jvm-memory/0.0.2?o=4&l=2&q===test1&m=true"}}
         String expectedResponse = "{\"response\":[{\"e\":\"test4\",\"b\":\"test1\"},{\"b\":\"test1\"}]," +
                 "\"metaData\":{\"payloadCount\":2,\"count\":6," +
-                "\"prev\":\"" + memoryUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d0\"," +
-                "\"next\":\"" + memoryUrl + "?o\\u003d4\\u0026l\\u003d2\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d0\"," +
+                "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d4\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&o=2&l=2", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=2&" + LIMIT_PREFIX + "=2", 200, expectedResponse);
     }
 
     @Test
@@ -419,10 +427,10 @@
         String expectedResponse = "{\"response\":[{\"e\":\"test4\",\"b\":\"test1\"}," +
                 "{\"b\":\"test1\"},{\"b\":\"test1\"}]," +
                 "\"metaData\":{\"payloadCount\":1,\"count\":6," +
-                "\"prev\":\"" + memoryUrl + "?q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\\u0026l\\u003d2\\u0026o\\u003d0\"," +
-                "\"next\":\"" + memoryUrl + "?o\\u003d5\\u0026l\\u003d1\\u0026q\\u003db\\u003d\\u003dtest1\\u0026m\\u003dtrue\"}}";
+                "\"prev\":\"" + returnedUrl + "?" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\\u0026" + LIMIT_PREFIX + "\\u003d2\\u0026" + OFFSET_PREFIX + "\\u003d0\"," +
+                "\"next\":\"" + returnedUrl + "?" + OFFSET_PREFIX + "\\u003d5\\u0026" + LIMIT_PREFIX + "\\u003d1\\u0026" + QUERY_PREFIX + "\\u003db\\u003d\\u003dtest1\\u0026" + METADATA_PREFIX + "\\u003dtrue\"}}";
 
         HttpTestUtil.addRecords(client, resourceUrl, data);
-        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?q=b==test1&m=true&o=2&l=3", 200, expectedResponse);
+        HttpTestUtil.testContentlessResponse(client, HttpMethod.GET, resourceUrl + "?" + QUERY_PREFIX + "=b==test1&" + METADATA_PREFIX + "=true&" + OFFSET_PREFIX + "=2&" + LIMIT_PREFIX + "=3", 200, expectedResponse);
     }
 }
--- a/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvms/JvmsServiceIntegrationTest.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/jvms/JvmsServiceIntegrationTest.java	Fri Jul 21 09:30:27 2017 -0400
@@ -49,6 +49,7 @@
 import com.redhat.thermostat.gateway.tests.integration.MongoIntegrationTest;
 
 public class JvmsServiceIntegrationTest extends MongoIntegrationTest {
+
     private static final String jvmsUrl = baseUrl + "/jvms/0.0.1";
 
     private final String postData = "[{ \"agentId\" : \"aid\", \"jvmId\" : \"jid1\", \"jvmPid\" : 1, \"startTime\" :" +
--- a/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/system/network/SystemNetworkIntegrationTest.java	Fri Jul 21 08:30:18 2017 -0400
+++ b/tests/integration-tests/src/test/java/com/redhat/thermostat/gateway/service/system/network/SystemNetworkIntegrationTest.java	Fri Jul 21 09:30:27 2017 -0400
@@ -190,8 +190,7 @@
     private ContentResponse post(final String systemid) throws InterruptedException, ExecutionException, TimeoutException {
         final Request request = client.newRequest(serviceURL + "/systems/" + systemid);
         request.header(HttpHeader.CONTENT_TYPE, "application/json");
-        //request.content(new StringContentProvider("[" + createJSON() + "]"));
-        request.content(new StringContentProvider(createJSON()));
+        request.content(new StringContentProvider( '[' + createJSON() + ']'));
         ContentResponse response = request.method(HttpMethod.POST).send();
         assertEquals(HTTP_200_OK, response.getStatus());
         final String expected = "";