diff --git a/bin/bindings.properties b/bin/bindings.properties
index 24ffa09f6453b259151a18df05b7b23514664da0..095bf9e570f4d1813eeab6756f908dd58b0665ce 100644
--- a/bin/bindings.properties
+++ b/bin/bindings.properties
@@ -30,15 +30,16 @@ aerospike:com.yahoo.ycsb.db.AerospikeClient
 asynchbase:com.yahoo.ycsb.db.AsyncHBaseClient
 arangodb:com.yahoo.ycsb.db.ArangoDBClient
 arangodb3:com.yahoo.ycsb.db.arangodb.ArangoDB3Client
+azuredocumentdb:com.yahoo.ycsb.db.azuredocumentdb.AzureDocumentDBClient
 azuretablestorage:com.yahoo.ycsb.db.azuretablestorage.AzureClient
 basic:com.yahoo.ycsb.BasicDB
 cassandra-cql:com.yahoo.ycsb.db.CassandraCQLClient
 cassandra2-cql:com.yahoo.ycsb.db.CassandraCQLClient
 couchbase:com.yahoo.ycsb.db.CouchbaseClient
 couchbase2:com.yahoo.ycsb.db.couchbase2.Couchbase2Client
-azuredocumentdb:com.yahoo.ycsb.db.azuredocumentdb.AzureDocumentDBClient
 dynamodb:com.yahoo.ycsb.db.DynamoDBClient
 elasticsearch:com.yahoo.ycsb.db.ElasticsearchClient
+elasticsearch5:com.yahoo.ycsb.db.elasticsearch5.ElasticsearchClient
 geode:com.yahoo.ycsb.db.GeodeClient
 googlebigtable:com.yahoo.ycsb.db.GoogleBigtableClient
 googledatastore:com.yahoo.ycsb.db.GoogleDatastoreClient
diff --git a/distribution/pom.xml b/distribution/pom.xml
index c2071adfd969244ba3a69c393b16a6ef461b814b..57d3fa8c9e54e8232df97ed7899406d94c7f8561 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -94,6 +94,11 @@ LICENSE file.
       <artifactId>elasticsearch-binding</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>com.yahoo.ycsb</groupId>
+      <artifactId>elasticsearch5-binding</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>com.yahoo.ycsb</groupId>
       <artifactId>geode-binding</artifactId>
diff --git a/elasticsearch/src/test/java/com/yahoo/ycsb/db/ElasticsearchClientTest.java b/elasticsearch/src/test/java/com/yahoo/ycsb/db/ElasticsearchClientTest.java
index d1ad64d187e642cfd2bf2eabc50f853c478b2825..a14f1a23c8d46bf70eb2fa74728fd9bf0fa42330 100644
--- a/elasticsearch/src/test/java/com/yahoo/ycsb/db/ElasticsearchClientTest.java
+++ b/elasticsearch/src/test/java/com/yahoo/ycsb/db/ElasticsearchClientTest.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2012 YCSB contributors. All rights reserved.
+ * Copyright (c) 2012-2017 YCSB contributors. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you
  * may not use this file except in compliance with the License. You
@@ -30,7 +30,6 @@ import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
@@ -44,15 +43,15 @@ import static org.junit.Assert.assertEquals;
 public class ElasticsearchClientTest {
 
     @ClassRule public final static TemporaryFolder temp = new TemporaryFolder();
-    protected final static ElasticsearchClient instance = new ElasticsearchClient();
-    protected final static HashMap<String, ByteIterator> MOCK_DATA;
-    protected final static String MOCK_TABLE = "MOCK_TABLE";
-    protected final static String MOCK_KEY0 = "0";
-    protected final static String MOCK_KEY1 = "1";
-    protected final static String MOCK_KEY2 = "2";
+    private final static ElasticsearchClient instance = new ElasticsearchClient();
+    private final static HashMap<String, ByteIterator> MOCK_DATA;
+    private final static String MOCK_TABLE = "MOCK_TABLE";
+    private final static String MOCK_KEY0 = "0";
+    private final static String MOCK_KEY1 = "1";
+    private final static String MOCK_KEY2 = "2";
 
     static {
-        MOCK_DATA = new HashMap<String, ByteIterator>(10);
+        MOCK_DATA = new HashMap<>(10);
         for (int i = 1; i <= 10; i++) {
             MOCK_DATA.put("field" + i, new StringByteIterator("value" + i));
         }
@@ -88,7 +87,6 @@ public class ElasticsearchClientTest {
      */
     @Test
     public void testInsert() {
-        System.out.println("insert");
         Status result = instance.insert(MOCK_TABLE, MOCK_KEY0, MOCK_DATA);
         assertEquals(Status.OK, result);
     }
@@ -98,7 +96,6 @@ public class ElasticsearchClientTest {
      */
     @Test
     public void testDelete() {
-        System.out.println("delete");
         Status result = instance.delete(MOCK_TABLE, MOCK_KEY1);
         assertEquals(Status.OK, result);
     }
@@ -108,9 +105,8 @@ public class ElasticsearchClientTest {
      */
     @Test
     public void testRead() {
-        System.out.println("read");
         Set<String> fields = MOCK_DATA.keySet();
-        HashMap<String, ByteIterator> resultParam = new HashMap<String, ByteIterator>(10);
+        HashMap<String, ByteIterator> resultParam = new HashMap<>(10);
         Status result = instance.read(MOCK_TABLE, MOCK_KEY1, fields, resultParam);
         assertEquals(Status.OK, result);
     }
@@ -120,9 +116,8 @@ public class ElasticsearchClientTest {
      */
     @Test
     public void testUpdate() {
-        System.out.println("update");
         int i;
-        HashMap<String, ByteIterator> newValues = new HashMap<String, ByteIterator>(10);
+        HashMap<String, ByteIterator> newValues = new HashMap<>(10);
 
         for (i = 1; i <= 10; i++) {
             newValues.put("field" + i, new StringByteIterator("newvalue" + i));
@@ -132,13 +127,12 @@ public class ElasticsearchClientTest {
         assertEquals(Status.OK, result);
 
         //validate that the values changed
-        HashMap<String, ByteIterator> resultParam = new HashMap<String, ByteIterator>(10);
+        HashMap<String, ByteIterator> resultParam = new HashMap<>(10);
         instance.read(MOCK_TABLE, MOCK_KEY1, MOCK_DATA.keySet(), resultParam);
 
         for (i = 1; i <= 10; i++) {
             assertEquals("newvalue" + i, resultParam.get("field" + i).toString());
         }
-
     }
 
     /**
@@ -146,10 +140,9 @@ public class ElasticsearchClientTest {
      */
     @Test
     public void testScan() {
-        System.out.println("scan");
         int recordcount = 10;
         Set<String> fields = MOCK_DATA.keySet();
-        Vector<HashMap<String, ByteIterator>> resultParam = new Vector<HashMap<String, ByteIterator>>(10);
+        Vector<HashMap<String, ByteIterator>> resultParam = new Vector<>(10);
         Status result = instance.scan(MOCK_TABLE, MOCK_KEY1, recordcount, fields, resultParam);
         assertEquals(Status.OK, result);
     }
diff --git a/elasticsearch5/README.md b/elasticsearch5/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..b87fc8749ba2074ce14dffab2aec0c655c8b90df
--- /dev/null
+++ b/elasticsearch5/README.md
@@ -0,0 +1,94 @@
+<!--
+Copyright (c) 2017 YCSB contributors. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you
+may not use this file except in compliance with the License. You
+may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied. See the License for the specific language governing
+permissions and limitations under the License. See accompanying
+LICENSE file.
+-->
+
+## Quick Start
+
+This section describes how to run YCSB on Elasticsearch 5.x running locally. 
+
+### 1. Set Up YCSB
+
+Clone the YCSB git repository and compile:
+
+    git clone git://github.com/brianfrankcooper/YCSB.git
+    cd YCSB
+    mvn clean package
+
+### 2. Run YCSB
+    
+Now you are ready to run! First, load the data:
+
+    ./bin/ycsb load elasticsearch5 -s -P workloads/workloada -p path.home=<path>
+
+Then, run the workload:
+
+    ./bin/ycsb run elasticsearch5 -s -P workloads/workloada -p path.home=<path>
+
+Note that the `<path>` specified in each execution should be the same.
+
+The Elasticsearch 5 binding has two modes of operation, embedded mode and remote
+mode. In embedded mode, the client creates an embedded instance of
+Elasticsearch that uses the specified `<path>` to persist data between
+executions.
+
+In remote mode, the client will hit a standalone instance of Elasticsearch. To
+use remote mode, add the flags `-p es.remote=true` and specify a hosts list via
+`-p es.hosts.list=<hostname1:port1>,...,<hostnamen:portn>`.
+
+    ./bin/ycsb run elasticsearch5 -s -P workloads/workloada -p es.remote=true \
+    -p es.hosts.list=<hostname1:port1>,...,<hostnamen:portn>`
+
+Note that `es.hosts.list` defaults to `localhost:9300`. For further
+configuration see below:
+
+### Defaults Configuration
+The default setting for the Elasticsearch node that is created is as follows:
+
+    cluster.name=es.ycsb.cluster
+    es.index.key=es.ycsb
+    es.number_of_shards=1
+    es.number_of_replicas=0
+    es.remote=false
+    es.newdb=false
+    es.hosts.list=localhost:9300 (only applies if es.remote=true)
+
+### Custom Configuration
+If you wish to customize the settings used to create the Elasticsearch node
+you can created a new property file that contains your desired Elasticsearch 
+node settings and pass it in via the parameter to 'bin/ycsb' script. Note that 
+the default properties will be kept if you don't explicitly overwrite them.
+
+Assuming that we have a properties file named "myproperties.data" that contains 
+custom Elasticsearch node configuration you can execute the following to
+pass it into the Elasticsearch client:
+
+
+    ./bin/ycsb run elasticsearch5 -P workloads/workloada -P myproperties.data -s
+
+If you wish to change the default index name you can set the following property:
+
+    es.index.key=my_index_key
+
+If you wish to run against a remote cluster you can set the following property:
+
+    es.remote=true
+
+By default this will use localhost:9300 as a seed node to discover the cluster.
+You can also specify
+
+    es.hosts.list=(\w+:\d+)+
+
+(a comma-separated list of host/port pairs) to change this.
diff --git a/elasticsearch5/pom.xml b/elasticsearch5/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3eb388084de5d63412f5a82085ba110bbd179bd4
--- /dev/null
+++ b/elasticsearch5/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+Copyright (c) 2017 YCSB contributors. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you
+may not use this file except in compliance with the License. You
+may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied. See the License for the specific language governing
+permissions and limitations under the License. See accompanying
+LICENSE file.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.yahoo.ycsb</groupId>
+    <artifactId>binding-parent</artifactId>
+    <version>0.13.0-SNAPSHOT</version>
+    <relativePath>../binding-parent</relativePath>
+  </parent>
+
+  <properties>
+    <!-- Skip tests by default. will be activated by jdk8 profile -->
+    <skipTests>true</skipTests>
+  </properties>
+
+  <artifactId>elasticsearch5-binding</artifactId>
+  <name>Elasticsearch 5.x Binding</name>
+  <packaging>jar</packaging>
+  <dependencies>
+    <dependency>
+      <!-- jna is supported in ES and will be used when provided
+           otherwise a fallback is used -->
+      <groupId>net.java.dev.jna</groupId>
+      <artifactId>jna</artifactId>
+      <version>4.1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>com.yahoo.ycsb</groupId>
+      <artifactId>core</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.elasticsearch.client</groupId>
+      <artifactId>transport</artifactId>
+      <version>${elasticsearch5-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.elasticsearch.client</groupId>
+      <artifactId>rest</artifactId>
+      <version>${elasticsearch5-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <version>2.7</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <version>2.7</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/elasticsearch5/src/main/java/com/yahoo/ycsb/db/elasticsearch5/ElasticsearchClient.java b/elasticsearch5/src/main/java/com/yahoo/ycsb/db/elasticsearch5/ElasticsearchClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..00cba31b9ae7c305ee09a5c15572d6abfa7377ba
--- /dev/null
+++ b/elasticsearch5/src/main/java/com/yahoo/ycsb/db/elasticsearch5/ElasticsearchClient.java
@@ -0,0 +1,274 @@
+/**
+ * Copyright (c) 2017 YCSB contributors. All rights reserved.
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License. See accompanying
+ * LICENSE file.
+ */
+
+package com.yahoo.ycsb.db.elasticsearch5;
+
+import com.yahoo.ycsb.*;
+import org.apache.http.HttpHost;
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
+import org.elasticsearch.action.delete.DeleteResponse;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.client.Requests;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.transport.TransportClient;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.transport.InetSocketTransportAddress;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.node.Node;
+import org.elasticsearch.node.NodeValidationException;
+import org.elasticsearch.rest.RestStatus;
+import org.elasticsearch.transport.client.PreBuiltTransportClient;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+import static org.elasticsearch.common.settings.Settings.Builder;
+import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+
+/**
+ * Elasticsearch client for YCSB framework.
+ */
+public class ElasticsearchClient extends DB {
+
+  private static final String DEFAULT_CLUSTER_NAME = "es.ycsb.cluster";
+  private static final String DEFAULT_INDEX_KEY = "es.ycsb";
+  private static final String DEFAULT_REMOTE_HOST = "localhost:9300";
+  private static final int NUMBER_OF_SHARDS = 1;
+  private static final int NUMBER_OF_REPLICAS = 0;
+  private Node node;
+  private Client client;
+  private String indexKey;
+  private Boolean remoteMode;
+
+  /**
+   * Initialize any state for this DB. Called once per DB instance; there is one
+   * DB instance per client thread.
+   */
+  @Override
+  public void init() throws DBException {
+    final Properties props = getProperties();
+
+    // Check if transport client needs to be used (To connect to multiple elasticsearch nodes)
+    remoteMode = Boolean.parseBoolean(props.getProperty("es.remote", "false"));
+
+    final String pathHome = props.getProperty("path.home");
+
+    // when running in embedded mode, require path.home
+    if (!remoteMode && (pathHome == null || pathHome.isEmpty())) {
+      throw new IllegalArgumentException("path.home must be specified when running in embedded mode");
+    }
+
+    this.indexKey = props.getProperty("es.index.key", DEFAULT_INDEX_KEY);
+
+    int numberOfShards = parseIntegerProperty(props, "es.number_of_shards", NUMBER_OF_SHARDS);
+    int numberOfReplicas = parseIntegerProperty(props, "es.number_of_replicas", NUMBER_OF_REPLICAS);
+
+    Boolean newdb = Boolean.parseBoolean(props.getProperty("es.newdb", "false"));
+    Builder settings = Settings.builder()
+        .put("cluster.name", DEFAULT_CLUSTER_NAME)
+        .put("path.home", pathHome);
+
+    // if properties file contains elasticsearch user defined properties
+    // add it to the settings file (will overwrite the defaults).
+    settings.put(props);
+    final String clusterName = settings.get("cluster.name");
+    System.err.println("Elasticsearch starting node = " + clusterName);
+    System.err.println("Elasticsearch node path.home = " + settings.get("path.home"));
+    System.err.println("Elasticsearch Remote Mode = " + remoteMode);
+    // Remote mode support for connecting to remote elasticsearch cluster
+    if(remoteMode) {
+      RestClient restClient = RestClient.builder(
+          new HttpHost("localhost", 9200, "http")).build();
+    }
+    if (remoteMode) {
+      settings.put("client.transport.sniff", true)
+          .put("client.transport.ignore_cluster_name", false)
+          .put("client.transport.ping_timeout", "30s")
+          .put("client.transport.nodes_sampler_interval", "30s");
+      // Default it to localhost:9300
+      String[] nodeList = props.getProperty("es.hosts.list", DEFAULT_REMOTE_HOST).split(",");
+      System.out.println("Elasticsearch Remote Hosts = " + props.getProperty("es.hosts.list", DEFAULT_REMOTE_HOST));
+      TransportClient tClient = new PreBuiltTransportClient(settings.build());
+      for (String h : nodeList) {
+        String[] nodes = h.split(":");
+        try {
+          tClient.addTransportAddress(new InetSocketTransportAddress(
+              InetAddress.getByName(nodes[0]),
+              Integer.parseInt(nodes[1])
+          ));
+        } catch (NumberFormatException e) {
+          throw new IllegalArgumentException("Unable to parse port number.", e);
+        } catch (UnknownHostException e) {
+          throw new IllegalArgumentException("Unable to Identify host.", e);
+        }
+      }
+      client = tClient;
+    } else { // Start node only if transport client mode is disabled
+      settings.put("transport.type", "local");
+      settings.put("http.enabled", "false");
+      node = new Node(settings.build());
+      try {
+        node.start();
+      } catch (NodeValidationException e) {
+        throw new DBException(e);
+      }
+      client = node.client();
+    }
+
+    final boolean exists =
+        client.admin().indices()
+            .exists(Requests.indicesExistsRequest(indexKey)).actionGet()
+            .isExists();
+    if (exists && newdb) {
+      client.admin().indices().prepareDelete(indexKey).execute().actionGet();
+    }
+    if (!exists || newdb) {
+      client.admin().indices().create(
+          new CreateIndexRequest(indexKey)
+              .settings(
+                  Settings.builder()
+                      .put("index.number_of_shards", numberOfShards)
+                      .put("index.number_of_replicas", numberOfReplicas)
+              )).actionGet();
+    }
+    client.admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet();
+  }
+
+  private int parseIntegerProperty(Properties properties, String key, int defaultValue) {
+    String value = properties.getProperty(key);
+    return value == null ? defaultValue : Integer.parseInt(value);
+  }
+
+  @Override
+  public void cleanup() throws DBException {
+    if (client != null) {
+      client.close();
+      client = null;
+    }
+
+    if (!remoteMode && node != null && !node.isClosed()) {
+      try {
+        node.close();
+        node = null;
+      } catch (IOException e) {
+        throw new DBException(e);
+      }
+    }
+  }
+
+  @Override
+  public Status insert(String table, String key, HashMap<String, ByteIterator> values) {
+    try {
+      final XContentBuilder doc = jsonBuilder().startObject();
+
+      for (Entry<String, String> entry : StringByteIterator.getStringMap(values).entrySet()) {
+        doc.field(entry.getKey(), entry.getValue());
+      }
+
+      doc.endObject();
+
+      client.prepareIndex(indexKey, table, key).setSource(doc).execute().actionGet();
+
+      return Status.OK;
+    } catch (Exception e) {
+      e.printStackTrace();
+      return Status.ERROR;
+    }
+  }
+
+  @Override
+  public Status delete(String table, String key) {
+    try {
+      DeleteResponse response = client.prepareDelete(indexKey, table, key).execute().actionGet();
+      if (response.status().equals(RestStatus.NOT_FOUND)) {
+        return Status.NOT_FOUND;
+      } else {
+        return Status.OK;
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      return Status.ERROR;
+    }
+  }
+
+  @Override
+  public Status read(String table, String key, Set<String> fields, HashMap<String, ByteIterator> result) {
+    try {
+      final GetResponse response = client.prepareGet(indexKey, table, key).execute().actionGet();
+
+      if (response.isExists()) {
+        if (fields != null) {
+          for (String field : fields) {
+            result.put(field, new StringByteIterator(
+                (String) response.getSource().get(field)));
+          }
+        } else {
+          for (String field : response.getSource().keySet()) {
+            result.put(field, new StringByteIterator(
+                (String) response.getSource().get(field)));
+          }
+        }
+        return Status.OK;
+      } else {
+        return Status.NOT_FOUND;
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      return Status.ERROR;
+    }
+  }
+
+  @Override
+  public Status update(String table, String key, HashMap<String, ByteIterator> values) {
+    try {
+      final GetResponse response = client.prepareGet(indexKey, table, key).execute().actionGet();
+
+      if (response.isExists()) {
+        for (Entry<String, String> entry : StringByteIterator.getStringMap(values).entrySet()) {
+          response.getSource().put(entry.getKey(), entry.getValue());
+        }
+
+        client.prepareIndex(indexKey, table, key).setSource(response.getSource()).execute().actionGet();
+
+        return Status.OK;
+      } else {
+        return Status.NOT_FOUND;
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      return Status.ERROR;
+    }
+  }
+
+  @Override
+  public Status scan(
+      String table,
+      String startkey,
+      int recordcount,
+      Set<String> fields,
+      Vector<HashMap<String, ByteIterator>> result) {
+    return Status.NOT_IMPLEMENTED;
+  }
+}
diff --git a/elasticsearch5/src/main/java/com/yahoo/ycsb/db/elasticsearch5/ElasticsearchRestClient.java b/elasticsearch5/src/main/java/com/yahoo/ycsb/db/elasticsearch5/ElasticsearchRestClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..e4f3c9e535740efec00ac52077f3e04049265b4a
--- /dev/null
+++ b/elasticsearch5/src/main/java/com/yahoo/ycsb/db/elasticsearch5/ElasticsearchRestClient.java
@@ -0,0 +1,218 @@
+/**
+ * Copyright (c) 2017 YCSB contributors. All rights reserved.
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License. See accompanying
+ * LICENSE file.
+ */
+
+package com.yahoo.ycsb.db.elasticsearch5;
+
+import com.yahoo.ycsb.*;
+import org.apache.http.HttpHost;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.entity.ContentType;
+import org.apache.http.nio.entity.NStringEntity;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.elasticsearch.client.Response;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.common.settings.Settings;
+
+import java.io.IOException;
+import java.util.*;
+
+import static org.elasticsearch.common.settings.Settings.Builder;
+
+/**
+ * Elasticsearch REST client for YCSB framework.
+ */
+public class ElasticsearchRestClient extends DB {
+
+  private static final String DEFAULT_CLUSTER_NAME = "es.ycsb.cluster";
+  private static final String DEFAULT_INDEX_KEY = "es.ycsb";
+  private static final String DEFAULT_REMOTE_HOST = "localhost:9200";
+  private static final int NUMBER_OF_SHARDS = 1;
+  private static final int NUMBER_OF_REPLICAS = 0;
+  private String indexKey;
+  private RestClient restClient;
+  
+  @Override
+  public void init() throws DBException {
+    final Properties props = getProperties();
+
+    this.indexKey = props.getProperty("es.index.key", DEFAULT_INDEX_KEY);
+
+    int numberOfShards = Integer.valueOf(props.getProperty("es.number_of_shards",
+        String.valueOf(NUMBER_OF_SHARDS)));
+    int numberOfReplicas = Integer.valueOf(props.getProperty("es.number_of_replicas",
+        String.valueOf(NUMBER_OF_REPLICAS)));
+
+    Boolean newdb = Boolean.parseBoolean(props.getProperty("es.newdb", "false"));
+    Builder settings = Settings.builder().put("cluster.name", DEFAULT_CLUSTER_NAME);
+
+    // if properties file contains elasticsearch user defined properties
+    // add it to the settings file (will overwrite the defaults).
+    settings.put(props);
+    final String clusterName = settings.get("cluster.name");
+    System.err.println("Elasticsearch starting node = " + clusterName);
+
+    String[] nodeList = props.getProperty("es.hosts.list", DEFAULT_REMOTE_HOST).split(",");
+    System.out.println("Elasticsearch Remote Hosts = " + props.getProperty("es.hosts.list", DEFAULT_REMOTE_HOST));
+
+    List<HttpHost> esHttpHosts = new ArrayList<>(nodeList.length);
+    for (String h : nodeList) {
+      String[] nodes = h.split(":");
+      esHttpHosts.add(new HttpHost(nodes[0], Integer.valueOf(nodes[1]), "http"));
+    }
+
+    restClient = RestClient.builder(esHttpHosts.toArray(new HttpHost[esHttpHosts.size()])).build();
+
+//    final boolean exists =
+//        client.admin().indices()
+//            .exists(Requests.indicesExistsRequest(indexKey)).actionGet()
+//            .isExists();
+//    if (exists && newdb) {
+//      client.admin().indices().prepareDelete(indexKey).execute().actionGet();
+//    }
+//    if (!exists || newdb) {
+//      client.admin().indices().create(
+//          new CreateIndexRequest(indexKey)
+//              .settings(
+//                  Settings.builder()
+//                      .put("index.number_of_shards", numberOfShards)
+//                      .put("index.number_of_replicas", numberOfReplicas)
+//              )).actionGet();
+//    }
+//    client.admin().cluster().health(new ClusterHealthRequest().waitForGreenStatus()).actionGet();
+  }
+
+  @Override
+  public void cleanup() throws DBException {
+    if (restClient != null) {
+      try {
+        restClient.close();
+        restClient = null;
+      } catch (IOException e) {
+        throw new DBException(e);
+      }
+    }
+  }
+  
+  @Override
+  public Status insert(String table, String key, HashMap<String, ByteIterator> values) {
+    try {
+      Map<String, String> data = StringByteIterator.getStringMap(values);
+
+      Response response = restClient.performRequest(
+          HttpPut.METHOD_NAME,
+          "/" + indexKey + "/" + table + "/",
+          Collections.<String, String>emptyMap(),
+          new NStringEntity(new ObjectMapper().writeValueAsString(data), ContentType.APPLICATION_JSON));
+
+      if(response.getStatusLine().getStatusCode() == 200) {
+        return Status.OK;
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return Status.ERROR;
+  }
+
+  @Override
+  public Status delete(String table, String key) {
+    try {
+      Response response = restClient.performRequest(
+          HttpDelete.METHOD_NAME,
+          "/" + indexKey + "/" + table + "/" + key);
+
+      if(response.getStatusLine().getStatusCode() == 200) {
+        return Status.OK;
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return Status.ERROR;
+  }
+
+  @Override
+  public Status read(String table, String key, Set<String> fields, HashMap<String, ByteIterator> result) {
+    try {
+      Response response = restClient.performRequest(HttpGet.METHOD_NAME, "/");
+
+      if(response.getStatusLine().getStatusCode() == 200) {
+        return Status.OK;
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return Status.ERROR;
+
+//    try {
+//      final GetResponse response = client.prepareGet(indexKey, table, key).execute().actionGet();
+//
+//      if (response.isExists()) {
+//        if (fields != null) {
+//          for (String field : fields) {
+//            result.put(field, new StringByteIterator(
+//                (String) response.getSource().get(field)));
+//          }
+//        } else {
+//          for (String field : response.getSource().keySet()) {
+//            result.put(field, new StringByteIterator(
+//                (String) response.getSource().get(field)));
+//          }
+//        }
+//        return Status.OK;
+//      } else {
+//        return Status.NOT_FOUND;
+//      }
+//    } catch (Exception e) {
+//      e.printStackTrace();
+//      return Status.ERROR;
+//    }
+  }
+
+  @Override
+  public Status update(String table, String key, HashMap<String, ByteIterator> values) {
+//    try {
+//      final GetResponse response = client.prepareGet(indexKey, table, key).execute().actionGet();
+//
+//      if (response.isExists()) {
+//        for (Entry<String, String> entry : StringByteIterator.getStringMap(values).entrySet()) {
+//          response.getSource().put(entry.getKey(), entry.getValue());
+//        }
+//
+//        client.prepareIndex(indexKey, table, key).setSource(response.getSource()).execute().actionGet();
+//
+//        return Status.OK;
+//      } else {
+//        return Status.NOT_FOUND;
+//      }
+//    } catch (Exception e) {
+//      e.printStackTrace();
+//      return Status.ERROR;
+//    }
+    return Status.NOT_IMPLEMENTED;
+  }
+
+  @Override
+  public Status scan(
+      String table,
+      String startkey,
+      int recordcount,
+      Set<String> fields,
+      Vector<HashMap<String, ByteIterator>> result) {
+    return Status.NOT_IMPLEMENTED;
+  }
+}
diff --git a/elasticsearch5/src/main/java/com/yahoo/ycsb/db/elasticsearch5/package-info.java b/elasticsearch5/src/main/java/com/yahoo/ycsb/db/elasticsearch5/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..6fef091471263b2c2afd4aa12f571d1bb8bc9382
--- /dev/null
+++ b/elasticsearch5/src/main/java/com/yahoo/ycsb/db/elasticsearch5/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2017 YCSB Contributors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License. See accompanying
+ * LICENSE file.
+ */
+
+/**
+ * The YCSB binding for 
+ * <a href="https://www.elastic.co/products/elasticsearch">Elasticsearch</a>.
+ */
+package com.yahoo.ycsb.db.elasticsearch5;
+
diff --git a/elasticsearch5/src/main/resources/log4j2.properties b/elasticsearch5/src/main/resources/log4j2.properties
new file mode 100644
index 0000000000000000000000000000000000000000..fced116e6bbf41ce9ac55fa93d13717474e19df1
--- /dev/null
+++ b/elasticsearch5/src/main/resources/log4j2.properties
@@ -0,0 +1,6 @@
+appender.console.type = Console
+appender.console.name = console
+appender.console.layout.type = PatternLayout
+
+rootLogger.level = info
+rootLogger.appenderRef.console.ref = console
\ No newline at end of file
diff --git a/elasticsearch5/src/test/java/com/yahoo/ycsb/db/elasticsearch5/ElasticsearchClientTest.java b/elasticsearch5/src/test/java/com/yahoo/ycsb/db/elasticsearch5/ElasticsearchClientTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..174c42ceab43acaef18dc3e8e773c91801f98104
--- /dev/null
+++ b/elasticsearch5/src/test/java/com/yahoo/ycsb/db/elasticsearch5/ElasticsearchClientTest.java
@@ -0,0 +1,146 @@
+/**
+ * Copyright (c) 2017 YCSB contributors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License. See accompanying
+ * LICENSE file.
+ */
+
+package com.yahoo.ycsb.db.elasticsearch5;
+
+import com.yahoo.ycsb.ByteIterator;
+import com.yahoo.ycsb.DBException;
+import com.yahoo.ycsb.Status;
+import com.yahoo.ycsb.StringByteIterator;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+import static org.junit.Assert.assertEquals;
+
+public class ElasticsearchClientTest {
+
+    @ClassRule public final static TemporaryFolder temp = new TemporaryFolder();
+    private final static ElasticsearchClient instance = new ElasticsearchClient();
+    private final static HashMap<String, ByteIterator> MOCK_DATA;
+    private final static String MOCK_TABLE = "MOCK_TABLE";
+    private final static String MOCK_KEY0 = "0";
+    private final static String MOCK_KEY1 = "1";
+    private final static String MOCK_KEY2 = "2";
+
+    static {
+        MOCK_DATA = new HashMap<>(10);
+        for (int i = 1; i <= 10; i++) {
+            MOCK_DATA.put("field" + i, new StringByteIterator("value" + i));
+        }
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws DBException {
+        final Properties props = new Properties();
+        props.put("path.home", temp.getRoot().toString());
+        instance.setProperties(props);
+        instance.init();
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws DBException {
+        instance.cleanup();
+    }
+
+    @Before
+    public void setUp() {
+        instance.insert(MOCK_TABLE, MOCK_KEY1, MOCK_DATA);
+        instance.insert(MOCK_TABLE, MOCK_KEY2, MOCK_DATA);
+    }
+
+    @After
+    public void tearDown() {
+        instance.delete(MOCK_TABLE, MOCK_KEY1);
+        instance.delete(MOCK_TABLE, MOCK_KEY2);
+    }
+
+    /**
+     * Test of insert method, of class ElasticsearchClient.
+     */
+    @Test
+    public void testInsert() {
+        Status result = instance.insert(MOCK_TABLE, MOCK_KEY0, MOCK_DATA);
+        assertEquals(Status.OK, result);
+    }
+
+    /**
+     * Test of delete method, of class ElasticsearchClient.
+     */
+    @Test
+    public void testDelete() {
+        Status result = instance.delete(MOCK_TABLE, MOCK_KEY1);
+        assertEquals(Status.OK, result);
+    }
+
+    /**
+     * Test of read method, of class ElasticsearchClient.
+     */
+    @Test
+    public void testRead() {
+        Set<String> fields = MOCK_DATA.keySet();
+        HashMap<String, ByteIterator> resultParam = new HashMap<>(10);
+        Status result = instance.read(MOCK_TABLE, MOCK_KEY1, fields, resultParam);
+        assertEquals(Status.OK, result);
+    }
+
+    /**
+     * Test of update method, of class ElasticsearchClient.
+     */
+    @Test
+    public void testUpdate() {
+        int i;
+        HashMap<String, ByteIterator> newValues = new HashMap<>(10);
+
+        for (i = 1; i <= 10; i++) {
+            newValues.put("field" + i, new StringByteIterator("newvalue" + i));
+        }
+
+        Status result = instance.update(MOCK_TABLE, MOCK_KEY1, newValues);
+        assertEquals(Status.OK, result);
+
+        //validate that the values changed
+        HashMap<String, ByteIterator> resultParam = new HashMap<>(10);
+        instance.read(MOCK_TABLE, MOCK_KEY1, MOCK_DATA.keySet(), resultParam);
+
+        for (i = 1; i <= 10; i++) {
+            assertEquals("newvalue" + i, resultParam.get("field" + i).toString());
+        }
+
+    }
+
+    /**
+     * Test of scan method, of class ElasticsearchClient.
+     */
+    @Test
+    public void testScan() {
+        int recordcount = 10;
+        Set<String> fields = MOCK_DATA.keySet();
+        Vector<HashMap<String, ByteIterator>> resultParam = new Vector<>(10);
+        Status result = instance.scan(MOCK_TABLE, MOCK_KEY1, recordcount, fields, resultParam);
+        assertEquals(Status.NOT_IMPLEMENTED, result);
+    }
+}
diff --git a/hypertable/pom.xml b/hypertable/pom.xml
index aa05f141169b740f05e8538f476df174313faf28..2f4bf01d1f3dd5cc01cdefbeaab927233d122645 100644
--- a/hypertable/pom.xml
+++ b/hypertable/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 
-Copyright (c) 2012 - 2016 YCSB contributors. All rights reserved.
+Copyright (c) 2012 - 2017 YCSB contributors. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License"); you
 may not use this file except in compliance with the License. You
@@ -40,7 +40,7 @@ LICENSE file.
     <dependency>
       <groupId>org.apache.thrift</groupId>
       <artifactId>libthrift</artifactId>
-      <version>${thrift.version}</version>
+      <version>0.8.0</version>
     </dependency>
     <dependency>
       <groupId>org.hypertable</groupId>
diff --git a/jdbc/pom.xml b/jdbc/pom.xml
index 9f6fdd1000771b5efee764752dd4e24a7e08a838..f33bbd9e0e866e37dfd35e9fad5eccc69e3d192e 100644
--- a/jdbc/pom.xml
+++ b/jdbc/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 
-Copyright (c) 2012 - 2016 YCSB contributors. All rights reserved.
+Copyright (c) 2012 - 2017 YCSB contributors. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License"); you
 may not use this file except in compliance with the License. You
@@ -33,7 +33,7 @@ LICENSE file.
     <dependency>
       <groupId>org.apache.openjpa</groupId>
       <artifactId>openjpa-jdbc</artifactId>
-      <version>${openjpa.jdbc.version}</version>
+      <version>2.1.1</version>
     </dependency>
     <dependency>
       <groupId>com.yahoo.ycsb</groupId>
diff --git a/pom.xml b/pom.xml
index 7693d2246931decc478cf12a100fdf36593f1e22..7a3a5f05788d121eecedaab2dbb0526dd44a00b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 
-Copyright (c) 2012 - 2016 YCSB contributors. All rights reserved.
+Copyright (c) 2012 - 2017 YCSB contributors. All rights reserved.
 
 Licensed under the Apache License, Version 2.0 (the "License"); you
 may not use this file except in compliance with the License. You
@@ -66,40 +66,43 @@ LICENSE file.
 
   <!-- Properties Management -->
   <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
     <maven.assembly.version>2.5.5</maven.assembly.version>
     <maven.dependency.version>2.10</maven.dependency.version>
+
+    <!-- Binding Versions -->
+    <accumulo.version>1.6.0</accumulo.version>
+    <aerospike.version>3.1.2</aerospike.version>
+    <arangodb.version>2.7.3</arangodb.version>
+    <arangodb3.version>4.1.7</arangodb3.version>
     <asynchbase.version>1.7.1</asynchbase.version>
+    <azuredocumentdb.version>1.8.1</azuredocumentdb.version>
+    <azurestorage.version>4.0.0</azurestorage.version>
+    <cassandra.cql.version>3.0.0</cassandra.cql.version>
+    <couchbase.version>1.4.10</couchbase.version>
+    <couchbase2.version>2.3.1</couchbase2.version>
     <hbase094.version>0.94.27</hbase094.version>
     <hbase098.version>0.98.14-hadoop2</hbase098.version>
     <hbase10.version>1.0.2</hbase10.version>
-    <accumulo.version>1.6.0</accumulo.version>
-    <cassandra.cql.version>3.0.0</cassandra.cql.version>
+    <hypertable.version>0.9.5.6</hypertable.version>
+    <elasticsearch-version>2.4.4</elasticsearch-version>
+    <elasticsearch5-version>5.2.0</elasticsearch5-version>
     <geode.version>1.0.0-incubating.M3</geode.version>
-    <azuredocumentdb.version>1.8.1</azuredocumentdb.version>
     <googlebigtable.version>0.2.3</googlebigtable.version>
     <infinispan.version>7.2.2.Final</infinispan.version>
     <kudu.version>1.1.0</kudu.version>
-    <openjpa.jdbc.version>2.1.1</openjpa.jdbc.version>
     <!--<mapkeeper.version>1.0</mapkeeper.version>-->
     <mongodb.version>3.0.3</mongodb.version>
     <mongodb.async.version>2.0.1</mongodb.async.version>
     <orientdb.version>2.2.10</orientdb.version>
     <redis.version>2.0.0</redis.version>
-    <s3.version>1.10.20</s3.version>
-    <voldemort.version>0.81</voldemort.version>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <thrift.version>0.8.0</thrift.version>
-    <hypertable.version>0.9.5.6</hypertable.version>
-    <couchbase.version>1.4.10</couchbase.version>
-    <couchbase2.version>2.3.1</couchbase2.version>
-    <tarantool.version>1.6.5</tarantool.version>
     <riak.version>2.0.5</riak.version>
-    <aerospike.version>3.1.2</aerospike.version>
+    <s3.version>1.10.20</s3.version>
     <solr.version>5.5.3</solr.version>
     <solr6.version>6.4.1</solr6.version>
-    <arangodb.version>2.7.3</arangodb.version>
-    <arangodb3.version>4.1.7</arangodb3.version>
-    <azurestorage.version>4.0.0</azurestorage.version>
+    <tarantool.version>1.6.5</tarantool.version>
+    <voldemort.version>0.81</voldemort.version>
   </properties>
 
   <modules>
@@ -120,6 +123,7 @@ LICENSE file.
     <module>azuredocumentdb</module>
     <module>dynamodb</module>
     <module>elasticsearch</module>
+    <module>elasticsearch5</module>
     <module>geode</module>
     <module>googlebigtable</module>
     <module>googledatastore</module>