merge documentation (that needs to be rewritten) with TLP graduation changes
diff --git a/README.md b/README.md
index 0691d30..855df60 100644
--- a/README.md
+++ b/README.md
@@ -9,3 +9,235 @@
 
 The repository is still in a very early state and lacks both unit tests and
 robust documentation.
+
+## Interaction
+
+Configuration and interaction with the server are done via JSON. We will
+demonstrate the main features of the server by creating a simple configuration
+and using that for some example requests and responses.
+
+Aside from configuration, all inputs may be sent as individual JSON objects or as
+a JSON Array. Also, the server does not implement a transactional database. In the event
+of an error partway through an array the server will return an error, but the
+effects of any requests processed up to that point will be retained.
+
+JSON input may be passed in via either POST or GET.
+
+
+### Sketch Families
+
+The server supports a variety of sketches suitable for different types of data analysis. For
+full details of the sketches, see the main Apache DataSketches website documentation. The
+key concepts used in the server are the sketch `family`, which determines the type of sketch, and
+in some cases a value `type`, which is used to interpret the input values.
+
+The known sketch families, the short name used in the server, and a description of the uses is
+summarized in the following table:
+
+| Short Name | Sketch Type      | Description |
+| ---------- | ---------------- | ----------- |
+| theta      | Theta Sketch     | Distinct counting with set operations |
+| hll        | HyperLogLog      | Distinct counting, no set operations |
+| cpc        | CPC              | Most compact distinct counting, no set operations |
+| kll        | KLL              | Absolute error quantiles sketch of floating point values |
+| frequency  | Frequent Items   | Heavy Hitters, items as strings |
+| reservoir  | Reservoir Sample | Uniform, unweighted random sample, items as strings |
+| varopt     | VarOpt Sample    | Weighted random sample for subset sum queries, items as strings |
+
+The three distinct counting sketches also require the specification of a value type so that items
+are presented to the sketch in a consistent way. The supported types are:
+
+| Type Name | Description |
+| --------- | ----------- |
+| int       | 32-bit signed integer |
+| long      | 64-bit signed integer |
+| float     | 32-bit floating-point value |
+| double    | 64-bit floating-point value |
+| string    | Java String |
+
+
+### Configuration
+
+The configuration file is passed in at server creation time.  Aside from the port, the configuration file defines the
+sketches held by the server. All sketches are instantiated at initialization, which keeps memory usage (mostly)
+constrained during operation. Keep in mind that quantiles sketches do grow indefinitely, although very slowly as the
+number of samples increases.
+
+Examples are taken from [conf.json][example/conf.json].
+
+There are two mechanisms for defining sketches. The first is an array of
+fully-described entries. The key for such an array must have a prefix `sketches`:
+```json
+{
+  "sketches_A": [
+    { "name": "cpc_int",
+      "k": 12,
+      "type": "int",
+      "family": "cpc"
+    },
+    { "name": "cpc_string",
+      "k": 12,
+      "type": "string",
+      "family": "cpc"
+    }
+  ]
+}
+   ```
+The above code creates two CPC sketches, `cpc_int` and `cpc_string`,
+holding `int` and `string` data, respectively, both configured with a log2(k) size
+parameter of 12. 
+
+In order to create multiple sketches with different names but otherwise
+configured identically, the key name must start with the prefix `set`:
+```json
+{
+  "set1": {
+    "k": 10,
+    "family": "hll",
+    "type": "double",
+    "names": [
+      "hll1",
+      "hll2",
+      "hll3"
+    ]
+  }
+}
+```
+or
+```json
+{
+  "set2": {
+    "k": 12,
+    "family": "theta",
+    "type": "float",
+    "names": [
+      "theta0",
+      "theta1",
+      "theta2",
+      "theta3",
+      "theta4"
+    ]
+  }
+}
+```
+The above examples create one set of 3 HLL sketches and one set of 5 theta sketches, respectively.
+
+### Supported Operations
+
+The available calls are:
+* `/update`
+* `/merge`
+* `/query`
+* `/serialize`
+* `/status`
+
+Each is described below, along with examples of input and output. As noted above, all calls accepting input may
+be invoked with either a single JSON object or a JSON Array of such objects.
+
+### Update
+
+Adding data is perhaps the key operation of a sketch. Each update key is the target sketch's name, and the value is
+either a single item or an array of items to be added to the sketch.
+
+For sketches that accept weighted values, specifically Frequent Items and VarOpt Sampling, passing in an item without a
+weight will be treated as having a weight of 1.0. To include a weight, the input must be a JSON object with both `item`
+and `weight`. An array of values to update may include a mix of plain, unweighted values and weighted input objects.
+
+An input to update may look like:
+```json
+{
+    "cpc_int": [1, 2, 2, 3, 4, 5],
+    "cpc_string": "single-item",
+    "fi": ["abc",
+	   { "item": "def", "weight": 3 },
+	   { "item": "ghi", "weight": 2 },
+	   "def"
+	  ],
+    "theta0": [1, 2, 3, 4, 5, 6],
+    "theta1": [5, 6, 7, 8, 9, 10]
+}
+```
+This example demonstrates the variety of inputs types, including repeated values, that are accepted by the server.
+
+There is no result returned from a successful call to update aside from the standard status code 200.
+
+```json
+{
+  "giveName": ["Alice", "Bob", "Cindy"], 
+  "heightInches": [62, 70, 64],
+  "postalCode": [12345, 11111, 94030]  
+}
+```
+
+### Merge
+
+
+
+
+### Query
+
+### Serialize
+
+### Status
+
+A query to the `/status` page returns a list of the configured sketches. There is no input to this query.
+
+Using `example/conf.json` to launch the server, a call to status returns:
+```json
+{
+  "count": 11,
+  "sketches": [
+    {
+      "name": "hll_3",
+      "type": "double",
+      "family": "hll"
+    },
+    {
+      "name": "hll_4",
+      "type": "double",
+      "family": "hll"
+    },
+    {
+      "name": "rs",
+      "family": "reservoir"
+    },
+    {
+      "name": "fi",
+      "family": "frequency"
+    },
+    {
+      "name": "hll_1",
+      "type": "double",
+      "family": "hll"
+    },
+    {
+      "name": "hll_2",
+      "type": "double",
+      "family": "hll"
+    },
+    {
+      "name": "cpc",
+      "type": "string",
+      "family": "cpc"
+    },
+    {
+      "name": "theta_string",
+      "type": "string",
+      "family": "theta"
+    },
+    {
+      "name": "theta_int",
+      "type": "int",
+      "family": "theta"
+    },
+    {
+      "name": "vo",
+      "family": "varopt"
+    },
+    {
+      "name": "kll",
+      "family": "kll"
+    }
+  ]
+}
+```
diff --git a/src/main/java/org/apache/datasketches/server/BaseSketchesQueryHandler.java b/src/main/java/org/apache/datasketches/server/BaseSketchesQueryHandler.java
index bad4af0..a3b1b8e 100644
--- a/src/main/java/org/apache/datasketches/server/BaseSketchesQueryHandler.java
+++ b/src/main/java/org/apache/datasketches/server/BaseSketchesQueryHandler.java
@@ -23,12 +23,14 @@
 import javax.servlet.http.HttpServletResponse;
 
 import java.io.IOException;
+import java.io.Reader;
 import java.net.URLDecoder;
 
 import org.apache.datasketches.Family;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.handler.AbstractHandler;
 
+import com.google.gson.GsonBuilder;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
@@ -41,7 +43,7 @@
  * <ul>
  *   <li>Extracts JSON query from querystring or POST body, as appropriate, to allow multiple input types.</li>
  *   <li>Sketches are stateful, and even reading can be disrupted by writes on another thread. A real
- *       database would have a more sophisticated locking system, but this class lets us syncrhonize across
+ *       database would have a more sophisticated locking system, but this class lets us synchronize across
  *       query types.</li>
  *   <li>Handles both JSON arrays or single JSON objects as inputs, letting the query handlers avoid
  *       code duplication.
@@ -57,7 +59,7 @@
    * Basic query handler. Assumes calls must include a JSON query.
    * @param sketches The sketches database to use
    */
-  BaseSketchesQueryHandler(SketchStorage sketches) {
+  BaseSketchesQueryHandler(final SketchStorage sketches) {
     this(sketches, false);
   }
 
@@ -66,7 +68,7 @@
    * @param sketches The sketches database to use
    * @param queryExempt <tt>true</tt> if a query is not required, otherwise <tt>false</tt>
    */
-  BaseSketchesQueryHandler(SketchStorage sketches, boolean queryExempt) {
+  BaseSketchesQueryHandler(final SketchStorage sketches, final boolean queryExempt) {
     if (sketches == null) {
       throw new IllegalArgumentException("Cannot initialize handler with SketchStorage == null");
     }
@@ -74,13 +76,15 @@
     this.queryExempt = queryExempt;
   }
 
-  JsonElement checkMethodAndReadJson(Request baseRequest,
-                                     HttpServletRequest request,
-                                     HttpServletResponse response) throws IOException {
+  static JsonElement checkMethodAndReadJson(final Request baseRequest,
+                                            final HttpServletRequest request,
+                                            final HttpServletResponse response) throws IOException {
     JsonElement query = null;
     if (request.getMethod().equals("POST")) {
       response.setContentType("application/json");
-      query = JsonParser.parseReader(request.getReader());
+      try (final Reader reader = request.getReader()) {
+        query = JsonParser.parseReader(reader);
+      }
     } else if (request.getMethod().equals("GET")) {
       response.setContentType("text/html");
       query = JsonParser.parseString(URLDecoder.decode(request.getQueryString(), "utf-8"));
@@ -104,15 +108,15 @@
    * @param query A JSON query to process
    * @return A JSON response
    */
-  final synchronized JsonObject callProcessQuery(JsonObject query) {
+  final synchronized JsonObject callProcessQuery(final JsonObject query) {
     return processQuery(query);
   }
 
   @Override
-  public void handle(String target,
-                     Request baseRequest,
-                     HttpServletRequest request,
-                     HttpServletResponse response) throws IOException {
+  public void handle(final String target,
+                     final Request baseRequest,
+                     final HttpServletRequest request,
+                     final HttpServletResponse response) throws IOException {
     JsonElement query = null;
     if (!queryExempt && ((query = checkMethodAndReadJson(baseRequest, request, response)) == null)) {
       return;
@@ -128,8 +132,8 @@
       if (query == null) {
         result = callProcessQuery(null);
       } else if (query.isJsonArray()) {
-        for (JsonElement subQuery : query.getAsJsonArray()) {
-          JsonObject subResult = callProcessQuery(subQuery.getAsJsonObject());
+        for (final JsonElement subQuery : query.getAsJsonArray()) {
+          final JsonObject subResult = callProcessQuery(subQuery.getAsJsonObject());
           if (subResult != null) {
             // lazy initialization to avoid possibly empty array
             if (result == null) {
@@ -143,14 +147,14 @@
       }
 
       if (result != null) {
-        response.getWriter().print(result.toString());
-        //response.getWriter().print(new GsonBuilder().setPrettyPrinting().create().toJson(result));
+        //response.getWriter().print(result.toString());
+        response.getWriter().print(new GsonBuilder().setPrettyPrinting().create().toJson(result));
       }
 
       // we're ok if we reach here without an exception
       response.setStatus(HttpServletResponse.SC_OK);
-    } catch (Exception e) {
-      JsonObject error = new JsonObject();
+    } catch (final Exception e) {
+      final JsonObject error = new JsonObject();
       error.addProperty(ERROR_KEY, e.getMessage());
       response.setStatus(UNPROCESSABLE_ENTITY);
     }
@@ -158,7 +162,7 @@
     baseRequest.setHandled(true);
   }
 
-  static Family familyFromString(String type) throws IllegalArgumentException {
+  static Family familyFromString(final String type) throws IllegalArgumentException {
     switch (type.toLowerCase()) {
       case SKETCH_FAMILY_THETA:
         return Family.QUICKSELECT;
diff --git a/src/main/java/org/apache/datasketches/server/DataQueryHandler.java b/src/main/java/org/apache/datasketches/server/DataQueryHandler.java
index 68255e4..c328eee 100644
--- a/src/main/java/org/apache/datasketches/server/DataQueryHandler.java
+++ b/src/main/java/org/apache/datasketches/server/DataQueryHandler.java
@@ -44,23 +44,23 @@
  * Full description to be added later.
  */
 public class DataQueryHandler extends BaseSketchesQueryHandler {
-  public DataQueryHandler(SketchStorage sketches) {
+  public DataQueryHandler(final SketchStorage sketches) {
     super(sketches, false);
   }
 
   @Override
-  protected JsonObject processQuery(JsonObject query) {
+  protected JsonObject processQuery(final JsonObject query) {
     if (!query.has(QUERY_NAME_FIELD)) {
       throw new IllegalArgumentException("Query missing sketch name field");
     }
 
-    String key = query.get(QUERY_NAME_FIELD).getAsString();
+    final String key = query.get(QUERY_NAME_FIELD).getAsString();
     if (!sketches.contains(key)) {
       throw new IllegalArgumentException("Invalid sketch name: " + key);
     }
 
-    SketchStorage.SketchEntry se = sketches.getSketch(key);
-    JsonObject result;
+    final SketchStorage.SketchEntry se = sketches.getSketch(key);
+    final JsonObject result;
 
     switch (se.family) {
       case UNION:
@@ -89,7 +89,7 @@
     return result;
   }
 
-  private boolean checkSummaryFlag(JsonObject query) {
+  private static boolean checkSummaryFlag(final JsonObject query) {
     boolean addSummary = false;
     if (query != null && query.has(QUERY_SUMMARY_FIELD)) {
       addSummary = query.get(QUERY_SUMMARY_FIELD).getAsBoolean();
@@ -97,27 +97,27 @@
     return addSummary;
   }
 
-  private JsonObject processDistinctQuery(JsonObject query, Family type, Object sketch) {
+  private static JsonObject processDistinctQuery(final JsonObject query, final Family type, final Object sketch) {
     if (query == null || type == null || sketch == null) {
       return null;
     }
 
     // check if we need a summary
-    boolean addSummary = checkSummaryFlag(query);
+    final boolean addSummary = checkSummaryFlag(query);
     String summary = null;
 
-    double estimate;
-    boolean isEstimationMode;
-    double p1StdDev;
-    double p2StdDev;
-    double p3StdDev;
-    double m1StdDev;
-    double m2StdDev;
-    double m3StdDev;
+    final double estimate;
+    final boolean isEstimationMode;
+    final double p1StdDev;
+    final double p2StdDev;
+    final double p3StdDev;
+    final double m1StdDev;
+    final double m2StdDev;
+    final double m3StdDev;
 
     switch (type) {
       case UNION:
-        CompactSketch thetaSketch = ((Union) sketch).getResult();
+        final CompactSketch thetaSketch = ((Union) sketch).getResult();
         isEstimationMode = thetaSketch.isEstimationMode();
         estimate = thetaSketch.getEstimate();
         p1StdDev = thetaSketch.getUpperBound(1);
@@ -130,7 +130,7 @@
         break;
 
       case CPC:
-        CpcSketch cpcSketch = (CpcSketch) sketch;
+        final CpcSketch cpcSketch = (CpcSketch) sketch;
         isEstimationMode = true; // no exact mode
         estimate = cpcSketch.getEstimate();
         p1StdDev = cpcSketch.getUpperBound(1);
@@ -143,7 +143,7 @@
         break;
 
       case HLL:
-        HllSketch hllSketch = (HllSketch) sketch;
+        final HllSketch hllSketch = (HllSketch) sketch;
         isEstimationMode = hllSketch.isEstimationMode();
         estimate = hllSketch.getEstimate();
         p1StdDev = hllSketch.getUpperBound(1);
@@ -159,7 +159,7 @@
         throw new IllegalArgumentException("Unknown distinct counting sketch type: " + type.toString());
     }
 
-    JsonObject result = new JsonObject();
+    final JsonObject result = new JsonObject();
     result.addProperty(RESPONSE_ESTIMATE_FIELD, estimate);
     result.addProperty(RESPONSE_ESTIMATION_MODE_FIELD, isEstimationMode);
     result.addProperty(RESPONSE_P1STDEV_FIELD, p1StdDev);
@@ -174,31 +174,31 @@
     return result;
   }
 
-  private JsonObject processQuantilesQuery(JsonObject query, Family type, Object sketch) {
+  private static JsonObject processQuantilesQuery(final JsonObject query, final Family type, final Object sketch) {
     if (query == null || type == null || sketch == null) {
       return null;
     }
 
     // check if we need a summary
-    boolean addSummary = checkSummaryFlag(query);
+    final boolean addSummary = checkSummaryFlag(query);
     String summary = null;
 
-    boolean isEstimationMode;
-    float maxValue;
-    float minValue;
-    long streamLength;
+    final boolean isEstimationMode;
+    final float maxValue;
+    final float minValue;
+    final long streamLength;
 
-    double[] fractions = getFractionsArray(query);
+    final double[] fractions = getFractionsArray(query);
     float[] quantiles = null;
 
-    float[] values = getValuesArray(query);
-    String resultType = getResultType(query);
+    final float[] values = getValuesArray(query);
+    final String resultType = getResultType(query);
     double[] ranks = null;
 
     // since we know REQ is coming
     switch (type) {
       case KLL:
-        KllFloatsSketch kll = (KllFloatsSketch) sketch;
+        final KllFloatsSketch kll = (KllFloatsSketch) sketch;
         isEstimationMode = kll.isEstimationMode();
         maxValue = kll.getMaxValue();
         minValue = kll.getMinValue();
@@ -220,7 +220,7 @@
         throw new SketchesException("processQuantilesQuery() received a non-quantiles sketch: " + type.toString());
     }
 
-    JsonObject result = new JsonObject();
+    final JsonObject result = new JsonObject();
     result.addProperty(RESPONSE_STREAM_LENGTH, streamLength);
     result.addProperty(RESPONSE_ESTIMATION_MODE_FIELD, isEstimationMode);
     result.addProperty(RESPONSE_MIN_VALUE, minValue);
@@ -228,9 +228,9 @@
 
     if (ranks != null) {
       final String label = resultType.equals(QUERY_RESULT_TYPE_PMF) ? RESPONSE_RESULT_MASS : RESPONSE_RESULT_RANK;
-      JsonArray rankArray = new JsonArray();
+      final JsonArray rankArray = new JsonArray();
       for (int i = 0; i < ranks.length; ++i) {
-        JsonObject rankPair = new JsonObject();
+        final JsonObject rankPair = new JsonObject();
         if (i == values.length) {
           rankPair.addProperty(RESPONSE_RESULT_VALUE, maxValue);
         } else {
@@ -247,9 +247,9 @@
     }
 
     if (quantiles != null) {
-      JsonArray quantileArray = new JsonArray();
+      final JsonArray quantileArray = new JsonArray();
       for (int i = 0; i < quantiles.length; ++i) {
-        JsonObject quantilePair = new JsonObject();
+        final JsonObject quantilePair = new JsonObject();
         quantilePair.addProperty(RESPONSE_RESULT_RANK, fractions[i]);
         quantilePair.addProperty(RESPONSE_RESULT_QUANTILE, quantiles[i]);
         quantileArray.add(quantilePair);
@@ -266,23 +266,23 @@
   // only one sketch type here so could use ItemsSketch<String> instead of Object, but
   // we'll eep the signatures generic here
   @SuppressWarnings("unchecked")
-  private JsonObject processFrequencyQuery(JsonObject query, Family type, Object sketch) {
+  private static JsonObject processFrequencyQuery(final JsonObject query, final Family type, final Object sketch) {
     if (query == null || type != Family.FREQUENCY || sketch == null) {
       return null;
     }
 
-    ItemsSketch<String> sk = (ItemsSketch<String>) sketch;
+    final ItemsSketch<String> sk = (ItemsSketch<String>) sketch;
 
     // check if we need a summary
-    boolean addSummary = checkSummaryFlag(query);
+    final boolean addSummary = checkSummaryFlag(query);
 
     if (!query.has(QUERY_ERRORTYPE_FIELD)) {
       throw new SketchesException("Must specify a value for " + QUERY_ERRORTYPE_FIELD
           + " for Frequent Items queries");
     }
 
-    ErrorType errorType;
-    String errorTypeString = query.get(QUERY_ERRORTYPE_FIELD).getAsString();
+    final ErrorType errorType;
+    final String errorTypeString = query.get(QUERY_ERRORTYPE_FIELD).getAsString();
     if (errorTypeString.equals(QUERY_ERRORTYPE_NO_FP)) {
       errorType = ErrorType.NO_FALSE_POSITIVES;
     } else if (errorTypeString.equals(QUERY_ERRORTYPE_NO_FN)) {
@@ -291,11 +291,11 @@
       throw new SketchesException("Unknown Frequent Items ErrorType: " + errorTypeString);
     }
 
-    ItemsSketch.Row<String>[] items = sk.getFrequentItems(errorType);
+    final ItemsSketch.Row<String>[] items = sk.getFrequentItems(errorType);
 
-    JsonArray itemArray = new JsonArray();
-    for (ItemsSketch.Row<String> item : items) {
-      JsonObject row = new JsonObject();
+    final JsonArray itemArray = new JsonArray();
+    for (final ItemsSketch.Row<String> item : items) {
+      final JsonObject row = new JsonObject();
       row.addProperty(RESPONSE_ITEM_VALUE, item.getItem());
       row.addProperty(RESPONSE_ITEM_ESTIMATE, item.getEstimate());
       row.addProperty(RESPONSE_ITEM_UPPER_BOUND, item.getUpperBound());
@@ -303,7 +303,7 @@
       itemArray.add(row);
     }
 
-    JsonObject result = new JsonObject();
+    final JsonObject result = new JsonObject();
     result.add(RESPONSE_ITEMS_ARRAY, itemArray);
     if (addSummary)
       result.addProperty(RESPONSE_SUMMARY_FIELD, sk.toString());
@@ -312,23 +312,23 @@
   }
 
   @SuppressWarnings("unchecked")
-  private JsonObject processSamplingQuery(JsonObject query, Family type, Object sketch) {
+  private static JsonObject processSamplingQuery(final JsonObject query, final Family type, final Object sketch) {
     if (query == null || type == null || sketch == null) {
       return null;
     }
 
     // check if we need a summary
-    boolean addSummary = checkSummaryFlag(query);
+    final boolean addSummary = checkSummaryFlag(query);
     String summary = null;
 
-    long streamWeight;
-    int k;
-    JsonArray itemArray = new JsonArray();
+    final long streamWeight;
+    final int k;
+    final JsonArray itemArray = new JsonArray();
 
     switch (type) {
       case RESERVOIR:
-        ReservoirItemsSketch<String> ris = (ReservoirItemsSketch<String>) sketch;
-        for (String item : ris.getSamples()) {
+        final ReservoirItemsSketch<String> ris = (ReservoirItemsSketch<String>) sketch;
+        for (final String item : ris.getSamples()) {
           itemArray.add(item);
         }
         streamWeight = ris.getN();
@@ -338,9 +338,9 @@
         break;
 
       case VAROPT:
-        VarOptItemsSketch<String> vis = (VarOptItemsSketch<String>) sketch;
-        for (VarOptItemsSamples<String>.WeightedSample ws : vis.getSketchSamples()) {
-          JsonObject item = new JsonObject();
+        final VarOptItemsSketch<String> vis = (VarOptItemsSketch<String>) sketch;
+        for (final VarOptItemsSamples<String>.WeightedSample ws : vis.getSketchSamples()) {
+          final JsonObject item = new JsonObject();
           item.addProperty(RESPONSE_ITEM_VALUE, ws.getItem());
           item.addProperty(RESPONSE_ITEM_WEIGHT, ws.getWeight());
           itemArray.add(item);
@@ -355,7 +355,7 @@
         throw new SketchesException("processSamplingQuery() received a non-sampling sketch: " + type.toString());
     }
 
-    JsonObject result = new JsonObject();
+    final JsonObject result = new JsonObject();
     result.addProperty(RESPONSE_SKETCH_K, k);
     result.addProperty(RESPONSE_STREAM_WEIGHT, streamWeight);
     result.add(RESPONSE_ITEMS_ARRAY, itemArray);
@@ -366,13 +366,13 @@
   }
 
   // returns an array of rank points, or null if none in query
-  private float[] getValuesArray(JsonObject query) {
+  private static float[] getValuesArray(final JsonObject query) {
     if (query == null || !query.has(QUERY_VALUES_FIELD_NAME)) {
       return null;
     }
 
-    JsonArray valuesArray = query.get(QUERY_VALUES_FIELD_NAME).getAsJsonArray();
-    float[] values = new float[valuesArray.size()];
+    final JsonArray valuesArray = query.get(QUERY_VALUES_FIELD_NAME).getAsJsonArray();
+    final float[] values = new float[valuesArray.size()];
 
     for (int i = 0; i < values.length; ++i) {
       if (!valuesArray.get(i).isJsonPrimitive()) {
@@ -386,16 +386,16 @@
 
   // returns QUERY_RESULT_TYPE_PMF if specified in QUERY_RESULT_TYPE_NAME_FIELD, otherwise returns default of
   // QUERY_RESULT_TYPE_CDF
-  private String getResultType(JsonObject query) {
+  private static String getResultType(final JsonObject query) {
     if (query == null || !query.has(QUERY_RESULT_TYPE_NAME_FIELD)) {
       return QUERY_RESULT_TYPE_CDF;
     }
 
-    JsonElement resultTypeElement = query.get(QUERY_RESULT_TYPE_NAME_FIELD);
+    final JsonElement resultTypeElement = query.get(QUERY_RESULT_TYPE_NAME_FIELD);
     if (!resultTypeElement.isJsonPrimitive())
       return QUERY_RESULT_TYPE_CDF;
 
-    String resultType = resultTypeElement.getAsString().toLowerCase();
+    final String resultType = resultTypeElement.getAsString().toLowerCase();
     if (resultType.equals(QUERY_RESULT_TYPE_PMF))
       return QUERY_RESULT_TYPE_PMF;
     else
@@ -403,13 +403,13 @@
   }
 
   // returns an array of provided split points, or null if none in query
-  private double[] getFractionsArray(JsonObject query) {
+  private static double[] getFractionsArray(final JsonObject query) {
     if (query == null || !query.has(QUERY_FRACTIONS_NAME_FIELD)) {
       return null;
     }
 
-    JsonArray fractionsArray = query.get(QUERY_FRACTIONS_NAME_FIELD).getAsJsonArray();
-    double[] fractions = new double[fractionsArray.size()];
+    final JsonArray fractionsArray = query.get(QUERY_FRACTIONS_NAME_FIELD).getAsJsonArray();
+    final double[] fractions = new double[fractionsArray.size()];
 
     for (int i = 0; i < fractions.length; ++i) {
       if (!fractionsArray.get(i).isJsonPrimitive()) {
diff --git a/src/main/java/org/apache/datasketches/server/MergeHandler.java b/src/main/java/org/apache/datasketches/server/MergeHandler.java
index ecc07e1..3966cf2 100644
--- a/src/main/java/org/apache/datasketches/server/MergeHandler.java
+++ b/src/main/java/org/apache/datasketches/server/MergeHandler.java
@@ -59,24 +59,24 @@
  * is not guaranteed.
  */
 public class MergeHandler extends BaseSketchesQueryHandler {
-  MergeHandler(SketchStorage sketches) {
+  MergeHandler(final SketchStorage sketches) {
     super(sketches);
   }
 
   @Override
-  protected JsonObject processQuery(JsonObject query) {
+  protected JsonObject processQuery(final JsonObject query) {
     // optional targets:
     // If no QUERY_MERGE_TGT_FIELD serialize the result, but then need specify QUERY_MERGE_K_FIELD.
     // If a valid target is present, any value of QUERY_MERGE_K_FIELD is ignored
-    JsonElement dstElement = query.get(SketchConstants.QUERY_MERGE_TGT_FIELD);
-    String dst = dstElement != null ? dstElement.getAsString() : null;
+    final JsonElement dstElement = query.get(SketchConstants.QUERY_MERGE_TGT_FIELD);
+    final String dst = dstElement != null ? dstElement.getAsString() : null;
     if (dst != null && !sketches.contains(dst)) {
       throw new IllegalArgumentException("Specified target sketch does not exist: " + dst);
     }
 
     int k = 0;
     if (dst == null) {
-      JsonElement kElement = query.get(SketchConstants.QUERY_MERGE_K_FIELD);
+      final JsonElement kElement = query.get(SketchConstants.QUERY_MERGE_K_FIELD);
       if (kElement == null) {
         throw new IllegalArgumentException("Must specify either \"" + SketchConstants.QUERY_MERGE_TGT_FIELD
             + "\" or \"" + SketchConstants.QUERY_MERGE_K_FIELD + "\". Neither found.");
@@ -84,11 +84,11 @@
       k = kElement.getAsInt();
     }
 
-    JsonElement srcElement = query.get(SketchConstants.QUERY_MERGE_SRC_FIELD);
+    final JsonElement srcElement = query.get(SketchConstants.QUERY_MERGE_SRC_FIELD);
     if (srcElement == null || !srcElement.isJsonArray()) {
       throw new IllegalArgumentException("Merge source data must be a JSON Array");
     }
-    JsonArray srcList = srcElement.getAsJsonArray();
+    final JsonArray srcList = srcElement.getAsJsonArray();
 
     SketchStorage.SketchEntry se = null;
     Family dstFamily = null;
@@ -99,14 +99,14 @@
 
     // we'll process (and dedup) any stored sketches before we handle encoded inputs
     // but we'll run through all of them before doing anything
-    ArrayList<Object> srcSketches = new ArrayList<>(srcList.size());
+    final ArrayList<Object> srcSketches = new ArrayList<>(srcList.size());
 
     dstFamily = prepareSketches(srcList, dstFamily, dst, srcSketches);
-    byte[] skBytes = mergeSketches(dstFamily, k, se, srcSketches);
+    final byte[] skBytes = mergeSketches(dstFamily, k, se, srcSketches);
 
     // skBytes == null if merging into another sketch; only non-null if returning a serialized image
     if (skBytes != null) {
-      JsonObject result = new JsonObject();
+      final JsonObject result = new JsonObject();
       result.addProperty(SketchConstants.QUERY_ENCODING_FIELD, SketchConstants.ENCODING_TYPE);
       result.addProperty(SketchConstants.QUERY_SKETCH_FIELD, Base64.getEncoder().encodeToString(skBytes));
       return result;
@@ -115,8 +115,8 @@
     }
   }
 
-  private Family prepareSketches(JsonArray sources, Family family, String dst, ArrayList<Object> sketchList) {
-    HashSet<String> namedSet = new HashSet<>();
+  private Family prepareSketches(final JsonArray sources, Family family, final String dst, final ArrayList<Object> sketchList) {
+    final HashSet<String> namedSet = new HashSet<>();
 
     // TODO: Check for sketch value types with distinct counting?
     //       Less obvious how to handle serialized sketch input in that case
@@ -126,11 +126,11 @@
       namedSet.add(dst);
     }
 
-    for (JsonElement elmt : sources) {
+    for (final JsonElement elmt : sources) {
       if (elmt.isJsonPrimitive()) {
         // check family
-        String key = elmt.getAsString();
-        SketchStorage.SketchEntry entry = sketches.getSketch(key);
+        final String key = elmt.getAsString();
+        final SketchStorage.SketchEntry entry = sketches.getSketch(key);
         if (entry == null || (family != null && family != entry.family)) {
           throw new SketchesException("Input sketches must exist and be of the same family as the target");
         }
@@ -151,21 +151,21 @@
         }
       } else { // is JsonObject
         // need special handling for theta as we store Unions?
-        JsonObject sourceObj = elmt.getAsJsonObject();
+        final JsonObject sourceObj = elmt.getAsJsonObject();
         if (!sourceObj.has(SketchConstants.QUERY_FAMILY_FIELD)
             || !sourceObj.has(SketchConstants.QUERY_DATA_FIELD)) {
           throw new SketchesException("Base64 sketch used as merge input must specify both \""
               + SketchConstants.QUERY_FAMILY_FIELD + "\" and \"" + SketchConstants.QUERY_DATA_FIELD + "\"");
         }
 
-        Family skFamily = familyFromString(sourceObj.get(SketchConstants.QUERY_FAMILY_FIELD).getAsString());
-        String skString = sourceObj.get(SketchConstants.QUERY_DATA_FIELD).getAsString();
+        final Family skFamily = familyFromString(sourceObj.get(SketchConstants.QUERY_FAMILY_FIELD).getAsString());
+        final String skString = sourceObj.get(SketchConstants.QUERY_DATA_FIELD).getAsString();
         if (skString == null || (family != null && family != skFamily)) {
           throw new SketchesException("Input sketches must exist and be of the same family as the target");
         }
 
         // add to list, save family if we didn't have one yet
-        Object sketch = deserializeSketch(skFamily, skString);
+        final Object sketch = deserializeSketch(skFamily, skString);
         sketchList.add(sketch);
         if (family == null) {
           family = skFamily;
@@ -176,12 +176,12 @@
     return family;
   }
 
-  private Object deserializeSketch(Family family, String b64String) {
+  private static Object deserializeSketch(final Family family, final String b64String) {
     if (family == null || b64String == null) {
       return null;
     }
 
-    Memory skBytes = Memory.wrap(Base64.getDecoder().decode(b64String));
+    final Memory skBytes = Memory.wrap(Base64.getDecoder().decode(b64String));
 
     switch (family) {
       case QUICKSELECT:
@@ -211,7 +211,8 @@
   }
 
   @SuppressWarnings("unchecked")
-  private byte[] mergeSketches(Family family, int k, SketchStorage.SketchEntry dstEntry, ArrayList<Object> sketchList) {
+  private static byte[] mergeSketches(final Family family, final int k,
+                                      final SketchStorage.SketchEntry dstEntry, final ArrayList<Object> sketchList) {
     if (family == null || sketchList.size() == 0) {
       return null;
     }
@@ -220,9 +221,9 @@
       case UNION:
       case QUICKSELECT: {
         // for HLL, the destination is already a union so no need to add explicitly
-        Union dst = dstEntry == null ? new SetOperationBuilder().setNominalEntries(1 << k).buildUnion()
+        final Union dst = dstEntry == null ? new SetOperationBuilder().setNominalEntries(1 << k).buildUnion()
             : (Union) dstEntry.sketch;
-        for (Object obj : sketchList) {
+        for (final Object obj : sketchList) {
           dst.update((CompactSketch) obj);
         }
 
@@ -235,11 +236,11 @@
       }
 
       case HLL: {
-        org.apache.datasketches.hll.Union union = new org.apache.datasketches.hll.Union(k);
+        final org.apache.datasketches.hll.Union union = new org.apache.datasketches.hll.Union(k);
         if (dstEntry != null) {
           union.update((HllSketch) dstEntry.sketch);
         }
-        for (Object obj : sketchList) {
+        for (final Object obj : sketchList) {
           union.update((HllSketch) obj);
         }
 
@@ -252,11 +253,11 @@
       }
 
       case CPC: {
-        CpcUnion union = new CpcUnion(k);
+        final CpcUnion union = new CpcUnion(k);
         if (dstEntry != null) {
           union.update((CpcSketch) dstEntry.sketch);
         }
-        for (Object obj : sketchList) {
+        for (final Object obj : sketchList) {
           union.update((CpcSketch) obj);
         }
 
@@ -270,9 +271,9 @@
 
       case KLL: {
         // Only merge(), no separate union. Slightly abusing terminology to call it union
-        KllFloatsSketch union = dstEntry == null ? new KllFloatsSketch(k) : (KllFloatsSketch) dstEntry.sketch;
+        final KllFloatsSketch union = dstEntry == null ? new KllFloatsSketch(k) : (KllFloatsSketch) dstEntry.sketch;
 
-        for (Object obj : sketchList) {
+        for (final Object obj : sketchList) {
           union.merge((KllFloatsSketch) obj);
         }
 
@@ -286,9 +287,9 @@
 
       case FREQUENCY: {
         // Only merge(), no separate union. Slightly abusing terminology to call it union
-        ItemsSketch<String> union = dstEntry == null ? new ItemsSketch<>(k) : (ItemsSketch<String>) dstEntry.sketch;
+        final ItemsSketch<String> union = dstEntry == null ? new ItemsSketch<>(k) : (ItemsSketch<String>) dstEntry.sketch;
 
-        for (Object obj : sketchList) {
+        for (final Object obj : sketchList) {
           union.merge((ItemsSketch<String>) obj);
         }
 
@@ -301,12 +302,12 @@
       }
 
       case RESERVOIR: {
-        ReservoirItemsUnion<String> union = ReservoirItemsUnion.newInstance(k);
+        final ReservoirItemsUnion<String> union = ReservoirItemsUnion.newInstance(k);
         if (dstEntry != null) {
           union.update((ReservoirItemsSketch<String>) dstEntry.sketch);
         }
 
-        for (Object obj : sketchList) {
+        for (final Object obj : sketchList) {
           union.update((ReservoirItemsSketch<String>) obj);
         }
 
@@ -319,12 +320,12 @@
       }
 
       case VAROPT: {
-        VarOptItemsUnion<String> union = VarOptItemsUnion.newInstance(k);
+        final VarOptItemsUnion<String> union = VarOptItemsUnion.newInstance(k);
         if (dstEntry != null) {
           union.update((VarOptItemsSketch<String>) dstEntry.sketch);
         }
 
-        for (Object obj : sketchList) {
+        for (final Object obj : sketchList) {
           union.update((VarOptItemsSketch<String>) obj);
         }
 
diff --git a/src/main/java/org/apache/datasketches/server/SerializationHandler.java b/src/main/java/org/apache/datasketches/server/SerializationHandler.java
index be78b4c..ce44ba6 100644
--- a/src/main/java/org/apache/datasketches/server/SerializationHandler.java
+++ b/src/main/java/org/apache/datasketches/server/SerializationHandler.java
@@ -44,25 +44,25 @@
  * </pre>
  */
 public class SerializationHandler extends BaseSketchesQueryHandler {
-  public SerializationHandler(SketchStorage sketches) {
+  public SerializationHandler(final SketchStorage sketches) {
     super(sketches, false);
   }
 
   @Override
   @SuppressWarnings("unchecked")
-  protected JsonObject processQuery(JsonObject query) {
+  protected JsonObject processQuery(final JsonObject query) {
     if (!query.has(QUERY_NAME_FIELD)) {
       throw new IllegalArgumentException("Query missing sketch name field");
     }
 
-    String name = query.get(QUERY_NAME_FIELD).getAsString();
+    final String name = query.get(QUERY_NAME_FIELD).getAsString();
     if (!sketches.contains(name)) {
       throw new IllegalArgumentException("Invalid sketch name: " + name);
     }
 
-    SketchStorage.SketchEntry se = sketches.getSketch(name);
+    final SketchStorage.SketchEntry se = sketches.getSketch(name);
 
-    byte[] bytes;
+    final byte[] bytes;
     switch (se.family) {
       case UNION:
         bytes = ((Union) se.sketch).getResult().toByteArray();
@@ -89,9 +89,9 @@
         throw new IllegalStateException("Unexpected value: " + se.family);
     }
 
-    String b64Sketch = Base64.getEncoder().encodeToString(bytes);
+    final String b64Sketch = Base64.getEncoder().encodeToString(bytes);
 
-    JsonObject result = new JsonObject();
+    final JsonObject result = new JsonObject();
     result.addProperty(QUERY_NAME_FIELD, name);
     result.addProperty(CONFIG_FAMILY_FIELD, se.family.getFamilyName());
     if (se.type != null)
diff --git a/src/main/java/org/apache/datasketches/server/SketchServer.java b/src/main/java/org/apache/datasketches/server/SketchServer.java
index eed38c4..6e4edce 100644
--- a/src/main/java/org/apache/datasketches/server/SketchServer.java
+++ b/src/main/java/org/apache/datasketches/server/SketchServer.java
@@ -27,6 +27,8 @@
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
 import org.eclipse.jetty.server.handler.ErrorHandler;
 
+import static org.apache.datasketches.server.SketchConstants.*;
+
 /**
  * Creates a very basic sketch server running embedded Jetty. Configuration options are specified in a config
  * file; for details @see SketchServerConfig.
@@ -39,7 +41,7 @@
   /**
    * Creates a server with the provided configuration
    * @param configFile Path to a configuration file following the <tt>SketchServerConfig</tt> format
-   * @throws IOException
+   * @throws IOException on parse errors
    */
   public SketchServer(final String configFile) throws IOException {
     config = new SketchServerConfig(configFile);
@@ -50,26 +52,26 @@
     server = new Server(config.getPort());
 
     // Error page unless you have a correct URL
-    ContextHandler contextRoot = new ContextHandler("/");
+    final ContextHandler contextRoot = new ContextHandler("/");
     contextRoot.setContextPath("/");
     contextRoot.setHandler(new ErrorHandler());
 
-    ContextHandler contextStatus = new ContextHandler(SketchConstants.STATUS_PATH);
+    final ContextHandler contextStatus = new ContextHandler(STATUS_PATH);
     contextStatus.setHandler(new StatusHandler(sketches));
 
-    ContextHandler contextSerialize = new ContextHandler(SketchConstants.SERIALIZE_PATH);
+    final ContextHandler contextSerialize = new ContextHandler(SERIALIZE_PATH);
     contextSerialize.setHandler(new SerializationHandler(sketches));
 
-    ContextHandler contextUpdate = new ContextHandler(SketchConstants.UPDATE_PATH);
+    final ContextHandler contextUpdate = new ContextHandler(UPDATE_PATH);
     contextUpdate.setHandler(new UpdateHandler(sketches));
 
-    ContextHandler contextMerge = new ContextHandler(SketchConstants.MERGE_PATH);
+    final ContextHandler contextMerge = new ContextHandler(MERGE_PATH);
     contextMerge.setHandler(new MergeHandler(sketches));
 
-    ContextHandler contextQuery = new ContextHandler(SketchConstants.QUERY_PATH);
+    final ContextHandler contextQuery = new ContextHandler(QUERY_PATH);
     contextQuery.setHandler(new DataQueryHandler(sketches));
 
-    ContextHandlerCollection contexts =
+    final ContextHandlerCollection contexts =
         new ContextHandlerCollection(contextRoot,
             contextStatus,
             contextSerialize,
@@ -81,7 +83,7 @@
 
   /**
    * Initializes the sketches, configures query handlers, and Starts the server.
-   * @throws Exception
+   * @throws Exception Relays exceptions from parsing config or running the server
    */
   public void start() throws Exception {
     sketches = new SketchStorage(config.getSketchList());
@@ -110,11 +112,11 @@
     return -1;
   }
 
-  public static void main(String[] args) throws Exception {
+  public static void main(final String[] args) throws Exception {
     //String confFile = args[0];
-    String confFile = "conf3.json";
+    final String confFile = "example/conf.json";
 
-    SketchServer sketchServer = new SketchServer(confFile);
+    final SketchServer sketchServer = new SketchServer(confFile);
     sketchServer.start();
   }
 }
diff --git a/src/main/java/org/apache/datasketches/server/SketchServerConfig.java b/src/main/java/org/apache/datasketches/server/SketchServerConfig.java
index 8a1a4c5..31a2daf 100644
--- a/src/main/java/org/apache/datasketches/server/SketchServerConfig.java
+++ b/src/main/java/org/apache/datasketches/server/SketchServerConfig.java
@@ -48,31 +48,28 @@
     public String family;
     public String type;
 
-    SketchInfo(String name, int k, String family, String type) {
+    SketchInfo(final String name, final int k, final String family, final String type) {
       this.name = name;
       this.k = k;
       this.family = family;
       this.type = type;
     }
 
-    SketchInfo(String name, int k, String family) {
-      this.name = name;
-      this.k = k;
-      this.family = family;
-      this.type = null;
+    SketchInfo(final String name, final int k, final String family) {
+      this(name, k, family, null);
     }
 
   }
 
-  private int port = SketchConstants.DEFAULT_PORT;
+  private int port = DEFAULT_PORT;
   private ArrayList<SketchInfo> sketchList;
 
-  SketchServerConfig(String configFile) throws IOException {
-    JsonElement config = readJsonFromFile(configFile);
+  SketchServerConfig(final String configFile) throws IOException {
+    final JsonElement config = readJsonFromFile(configFile);
     parseConfig(config);
   }
 
-  SketchServerConfig(JsonElement config) throws IOException {
+  SketchServerConfig(final JsonElement config) throws IOException {
     parseConfig(config);
   }
 
@@ -86,22 +83,20 @@
 
   // output should have a list with full info per sketch, even if input allows a
   // more condensed format
-  private JsonElement readJsonFromFile(String configFile) {
+  private static JsonElement readJsonFromFile(final String configFile) {
     JsonElement config = null;
 
-    try {
-      Reader reader = Files.newBufferedReader(Paths.get(configFile));
+    try (final Reader reader = Files.newBufferedReader(Paths.get(configFile))) {
       config = JsonParser.parseReader(reader);
-      reader.close();
-    } catch (IOException e) {
+    } catch (final IOException e) {
       e.printStackTrace();
     }
 
     return config;
   }
 
-  private void parseConfig(JsonElement config) throws IOException {
-    Gson gson = new Gson();
+  private void parseConfig(final JsonElement config) throws IOException {
+    final Gson gson = new Gson();
 
     sketchList = new ArrayList<>();
 
@@ -109,9 +104,9 @@
       // must be a list of fully-described sketches
       sketchList.addAll(Arrays.asList(gson.fromJson(config.getAsJsonArray(), SketchInfo[].class)));
     } else if (config.isJsonObject()) {
-      JsonObject confEntry = config.getAsJsonObject();
-      for (String name : confEntry.keySet()) {
-        if (name.toLowerCase().equals(CONFIG_PORT_FIELD)) {
+      final JsonObject confEntry = config.getAsJsonObject();
+      for (final String name : confEntry.keySet()) {
+        if (name.equalsIgnoreCase(CONFIG_PORT_FIELD)) {
           // port the server should use
           port = confEntry.get(name).getAsInt();
         }
@@ -120,16 +115,16 @@
           sketchList.addAll(Arrays.asList(gson.fromJson(confEntry.get(name).getAsJsonArray(), SketchInfo[].class)));
         } else if (name.toLowerCase().startsWith(CONFIG_SET_PREFIX)) {
           // set* has a common name and type with an array of name names
-          JsonObject sketchSetInfo = confEntry.get(name).getAsJsonObject();
-          int k = sketchSetInfo.get(CONFIG_K_FIELD).getAsInt();
-          String family = sketchSetInfo.get(CONFIG_FAMILY_FIELD).getAsString();
+          final JsonObject sketchSetInfo = confEntry.get(name).getAsJsonObject();
+          final int k = sketchSetInfo.get(CONFIG_K_FIELD).getAsInt();
+          final String family = sketchSetInfo.get(CONFIG_FAMILY_FIELD).getAsString();
           String type = null;
           if (isDistinctCounting(BaseSketchesQueryHandler.familyFromString(family))) {
             type = sketchSetInfo.get(CONFIG_TYPE_FIELD).getAsString();
           }
-          String[] nameList = gson.fromJson(sketchSetInfo.get(CONFIG_SET_NAMES_FIELD).getAsJsonArray(), String[].class);
+          final String[] nameList = gson.fromJson(sketchSetInfo.get(CONFIG_SET_NAMES_FIELD).getAsJsonArray(), String[].class);
 
-          for (String n : nameList)
+          for (final String n : nameList)
             sketchList.add(new SketchInfo(n, k, family, type));
         }
       }
diff --git a/src/main/java/org/apache/datasketches/server/SketchStorage.java b/src/main/java/org/apache/datasketches/server/SketchStorage.java
index dd4b1ed..5c21de8 100644
--- a/src/main/java/org/apache/datasketches/server/SketchStorage.java
+++ b/src/main/java/org/apache/datasketches/server/SketchStorage.java
@@ -59,7 +59,7 @@
     public final ValueType type;
     public Object sketch;
 
-    SketchEntry(Family family, ValueType type, Object sketch) throws IllegalArgumentException {
+    SketchEntry(final Family family, final ValueType type, final Object sketch) throws IllegalArgumentException {
       if (isDistinctCounting(family) && type == null)
         throw new IllegalArgumentException("Must specify a value type for distinct counting sketches");
 
@@ -68,7 +68,7 @@
       this.sketch = sketch;
     }
 
-    SketchEntry(Family family, Object sketch) throws IllegalArgumentException {
+    SketchEntry(final Family family, final Object sketch) throws IllegalArgumentException {
       if (isDistinctCounting(family))
         throw new IllegalArgumentException("Must specify a value type for distinct counting sketches");
 
@@ -80,18 +80,18 @@
 
   HashMap<String, SketchEntry> sketchMap;
 
-  SketchStorage(List<SketchServerConfig.SketchInfo> sketchList) {
+  SketchStorage(final List<SketchServerConfig.SketchInfo> sketchList) {
     if (sketchList != null) {
       createSketches(sketchList);
     }
   }
 
   JsonObject listSketches() {
-    JsonObject summary = new JsonObject();
+    final JsonObject summary = new JsonObject();
 
-    JsonArray sketchList = new JsonArray(sketchMap.size());
-    for (Map.Entry<String, SketchEntry> e : sketchMap.entrySet()) {
-      JsonObject item = new JsonObject();
+    final JsonArray sketchList = new JsonArray(sketchMap.size());
+    for (final Map.Entry<String, SketchEntry> e : sketchMap.entrySet()) {
+      final JsonObject item = new JsonObject();
       item.addProperty(CONFIG_SKETCH_NAME_FIELD, e.getKey());
       switch (e.getValue().family) {
         case UNION:
@@ -128,25 +128,25 @@
     return summary;
   }
 
-  boolean contains(String key) {
+  boolean contains(final String key) {
      return sketchMap.containsKey(key);
   }
 
-  SketchEntry getSketch(String key) {
+  SketchEntry getSketch(final String key) {
     return sketchMap.get(key);
   }
 
   // instantiate the actual sketches, throwing if there's a duplicate key
-  private void createSketches(List<SketchServerConfig.SketchInfo> list) throws IllegalArgumentException {
+  private void createSketches(final List<SketchServerConfig.SketchInfo> list) throws IllegalArgumentException {
     sketchMap = new HashMap<>(list.size());
 
-    for (SketchServerConfig.SketchInfo info : list) {
+    for (final SketchServerConfig.SketchInfo info : list) {
       if (sketchMap.containsKey(info.name)) {
         throw new IllegalArgumentException("Duplicate sketch key: " + info.name);
       }
 
       SketchEntry sketchEntry = null;
-      Family family = BaseSketchesQueryHandler.familyFromString(info.family);
+      final Family family = BaseSketchesQueryHandler.familyFromString(info.family);
 
       switch (family) {
         case QUICKSELECT:
diff --git a/src/main/java/org/apache/datasketches/server/StatusHandler.java b/src/main/java/org/apache/datasketches/server/StatusHandler.java
index d782a12..0f44f15 100644
--- a/src/main/java/org/apache/datasketches/server/StatusHandler.java
+++ b/src/main/java/org/apache/datasketches/server/StatusHandler.java
@@ -26,12 +26,12 @@
  */
 public class StatusHandler extends BaseSketchesQueryHandler {
 
-  public StatusHandler(SketchStorage sketches) {
+  public StatusHandler(final SketchStorage sketches) {
     super(sketches, true);
   }
 
   @Override
-  protected JsonObject processQuery(JsonObject query) {
+  protected JsonObject processQuery(final JsonObject query) {
     return sketches.listSketches();
   }
 }
diff --git a/src/main/java/org/apache/datasketches/server/UpdateHandler.java b/src/main/java/org/apache/datasketches/server/UpdateHandler.java
index 2cc362f..eb8c97a 100644
--- a/src/main/java/org/apache/datasketches/server/UpdateHandler.java
+++ b/src/main/java/org/apache/datasketches/server/UpdateHandler.java
@@ -52,7 +52,7 @@
  * Each <em>value</em> may be a stand-alone item or, for sketches accepting weighted inputs, may be a JSON
  * object: <tt>{ "item": &lt;value&gt;, "weight": &lt;weight&gt; }</tt>. Attempting to use a weight with a
  * sketch that does not support weighted inputs will result in an error. The multi-value update format
- * may contain a mux of weighted and unweighted items, as lonig s the sketch accepts weighted values.
+ * may contain a mux of weighted and unweighted items, as long s the sketch accepts weighted values.
  * </p>
  * <p>
  * The JSON parsing library does not allow duplicate key names; to send multiple values into the same sketch
@@ -65,16 +65,16 @@
  * </p>
  */
 public class UpdateHandler extends BaseSketchesQueryHandler {
-  public UpdateHandler(SketchStorage sketches) {
+  public UpdateHandler(final SketchStorage sketches) {
     super(sketches);
   }
 
   @Override
-  protected JsonObject processQuery(JsonObject query) {
-    for (Map.Entry<String, JsonElement> entry : query.entrySet()) {
-      String name = entry.getKey();
-      SketchStorage.SketchEntry se = sketches.getSketch(name);
-      JsonElement data = entry.getValue();
+  protected JsonObject processQuery(final JsonObject query) {
+    for (final Map.Entry<String, JsonElement> entry : query.entrySet()) {
+      final String name = entry.getKey();
+      final SketchStorage.SketchEntry se = sketches.getSketch(name);
+      final JsonElement data = entry.getValue();
 
       if (name == null || se == null || data == null) {
         throw new IllegalArgumentException("Attempt to call update with missing name or sketch not found");
@@ -92,20 +92,20 @@
   }
 
   @SuppressWarnings("unchecked")
-  private void processBatchUpdate(SketchStorage.SketchEntry entry,
-                                  JsonArray data) {
+  private static void processBatchUpdate(final SketchStorage.SketchEntry entry,
+                                         final JsonArray data) {
     switch (entry.family) {
       case UNION: // theta
         assert(entry.type != null);
         switch (entry.type) {
           case FLOAT: case DOUBLE:
-            for (JsonElement e : data) { ((Union) entry.sketch).update(e.getAsDouble()); }
+            for (final JsonElement e : data) { ((Union) entry.sketch).update(e.getAsDouble()); }
             break;
           case INT: case LONG:
-            for (JsonElement e : data) { ((Union) entry.sketch).update(e.getAsLong()); }
+            for (final JsonElement e : data) { ((Union) entry.sketch).update(e.getAsLong()); }
             break;
           case STRING: default:
-            for (JsonElement e : data) { ((Union) entry.sketch).update(e.getAsString()); }
+            for (final JsonElement e : data) { ((Union) entry.sketch).update(e.getAsString()); }
             break;
         }
         break;
@@ -114,13 +114,13 @@
         assert(entry.type != null);
         switch (entry.type) {
           case FLOAT: case DOUBLE:
-            for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsDouble()); }
+            for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsDouble()); }
             break;
           case INT: case LONG:
-            for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsLong()); }
+            for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsLong()); }
             break;
           case STRING: default:
-            for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsString()); }
+            for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsString()); }
             break;
         }
         break;
@@ -129,31 +129,31 @@
         assert(entry.type != null);
         switch (entry.type) {
           case FLOAT: case DOUBLE:
-            for (JsonElement e : data) { ((HllSketch) entry.sketch).update(e.getAsDouble()); }
+            for (final JsonElement e : data) { ((HllSketch) entry.sketch).update(e.getAsDouble()); }
             break;
           case INT: case LONG:
-            for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsLong()); }
+            for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsLong()); }
             break;
           case STRING: default:
-            for (JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsString()); }
+            for (final JsonElement e : data) { ((CpcSketch) entry.sketch).update(e.getAsString()); }
             break;
         }
         break;
 
       case KLL:
-        for (JsonElement e : data) { ((KllFloatsSketch) entry.sketch).update(e.getAsFloat()); }
+        for (final JsonElement e : data) { ((KllFloatsSketch) entry.sketch).update(e.getAsFloat()); }
         break;
 
       case FREQUENCY:
-        for (JsonElement e : data) {
+        for (final JsonElement e : data) {
           if (e.isJsonObject()) {
-            JsonObject inputPair = e.getAsJsonObject();
+            final JsonObject inputPair = e.getAsJsonObject();
             if (!inputPair.has(QUERY_PAIR_ITEM_FIELD) || !inputPair.has(QUERY_PAIR_WEIGHT_FIELD)) {
               throw new IllegalArgumentException("Frequent Items input pairs must include both "
                   + QUERY_PAIR_ITEM_FIELD + " and " + QUERY_PAIR_WEIGHT_FIELD + " values");
             }
-            String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
-            int weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsInt();
+            final String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
+            final int weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsInt();
             ((ItemsSketch<String>) entry.sketch).update(item, weight);
           } else {
             ((ItemsSketch<String>) entry.sketch).update(e.getAsString());
@@ -162,19 +162,19 @@
         break;
 
       case RESERVOIR:
-        for (JsonElement e : data) { ((ReservoirItemsSketch<String>) entry.sketch).update(e.getAsString()); }
+        for (final JsonElement e : data) { ((ReservoirItemsSketch<String>) entry.sketch).update(e.getAsString()); }
         break;
 
       case VAROPT:
-        for (JsonElement e : data) {
+        for (final JsonElement e : data) {
           if (e.isJsonObject()) {
-            JsonObject inputPair = e.getAsJsonObject();
+            final JsonObject inputPair = e.getAsJsonObject();
             if (!inputPair.has(QUERY_PAIR_ITEM_FIELD) || !inputPair.has(QUERY_PAIR_WEIGHT_FIELD)) {
               throw new IllegalArgumentException("VarOpt input pairs must include both "
                   + QUERY_PAIR_ITEM_FIELD + " and " + QUERY_PAIR_WEIGHT_FIELD + " values");
             }
-            String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
-            double weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsDouble();
+            final String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
+            final double weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsDouble();
             ((VarOptItemsSketch<String>) entry.sketch).update(item, weight);
           } else {
             ((VarOptItemsSketch<String>) entry.sketch).update(e.getAsString(), 1.0);
@@ -188,8 +188,8 @@
   }
 
   @SuppressWarnings("unchecked")
-  private void processSingleUpdate(SketchStorage.SketchEntry entry,
-                                   JsonElement data) {
+  private static void processSingleUpdate(final SketchStorage.SketchEntry entry,
+                                          final JsonElement data) {
     switch (entry.family) {
       case UNION:
         assert(entry.type != null);
@@ -242,13 +242,13 @@
 
       case FREQUENCY:
         if (data.isJsonObject()) {
-          JsonObject inputPair = data.getAsJsonObject();
+          final JsonObject inputPair = data.getAsJsonObject();
           if (!inputPair.has(QUERY_PAIR_ITEM_FIELD) || !inputPair.has(QUERY_PAIR_WEIGHT_FIELD)) {
             throw new IllegalArgumentException("Frequent Items input pairs must include both "
                 + QUERY_PAIR_ITEM_FIELD + " and " + QUERY_PAIR_WEIGHT_FIELD + " values");
           }
-          String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
-          int weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsInt();
+          final String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
+          final int weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsInt();
           ((ItemsSketch<String>) entry.sketch).update(item, weight);
         } else {
           ((ItemsSketch<String>) entry.sketch).update(data.getAsString());
@@ -261,13 +261,13 @@
 
       case VAROPT:
         if (data.isJsonObject()) {
-          JsonObject inputPair = data.getAsJsonObject();
+          final JsonObject inputPair = data.getAsJsonObject();
           if (!inputPair.has(QUERY_PAIR_ITEM_FIELD) || !inputPair.has(QUERY_PAIR_WEIGHT_FIELD)) {
             throw new IllegalArgumentException("VarOpt input pairs must include both "
                 + QUERY_PAIR_ITEM_FIELD + " and " + QUERY_PAIR_WEIGHT_FIELD + " values");
           }
-          String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
-          double weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsDouble();
+          final String item = inputPair.get(QUERY_PAIR_ITEM_FIELD).getAsString();
+          final double weight = inputPair.get(QUERY_PAIR_WEIGHT_FIELD).getAsDouble();
           ((VarOptItemsSketch<String>) entry.sketch).update(item, weight);
         } else {
           ((VarOptItemsSketch<String>) entry.sketch).update(data.getAsString(), 1.0);
diff --git a/src/main/java/org/apache/datasketches/server/ValueType.java b/src/main/java/org/apache/datasketches/server/ValueType.java
index 0ec1ff9..6bde33e 100644
--- a/src/main/java/org/apache/datasketches/server/ValueType.java
+++ b/src/main/java/org/apache/datasketches/server/ValueType.java
@@ -56,7 +56,7 @@
   private final String typeName_;
 
   static {
-    for (ValueType t : values()) {
+    for (final ValueType t : values()) {
       lookupTypeName.put(t.getTypeName().toLowerCase(), t);
     }
   }