Repository: googleapis/java-bigtable-hbase
Pull request #2396 (2020-03-04 18:43:47)

refactor: moved logger from core to hbase module
`com.google.cloud.bigtable.config.Logger` is referenced by internal classes of `bigtable-hbase` module. This change is to copy it to `bigtable-hbase`.


Patch:
diff --git a/bigtable-client-core-parent/bigtable-client-core/pom.xml b/bigtable-client-core-parent/bigtable-client-core/pom.xml
index 55dcc7792..33a5d9042 100644
--- a/bigtable-client-core-parent/bigtable-client-core/pom.xml
+++ b/bigtable-client-core-parent/bigtable-client-core/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-client-core-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-client-core</artifactId>
diff --git a/bigtable-client-core-parent/bigtable-hbase/pom.xml b/bigtable-client-core-parent/bigtable-hbase/pom.xml
index a2aa5b776..d09fa5f12 100644
--- a/bigtable-client-core-parent/bigtable-hbase/pom.xml
+++ b/bigtable-client-core-parent/bigtable-hbase/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-client-core-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-hbase</artifactId>
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/AbstractBigtableRegionLocator.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/AbstractBigtableRegionLocator.java
index f6c96491b..95cc18b09 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/AbstractBigtableRegionLocator.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/AbstractBigtableRegionLocator.java
@@ -23,11 +23,11 @@ import com.google.api.core.ApiFutureCallback;
 import com.google.api.core.ApiFutures;
 import com.google.api.core.InternalApi;
 import com.google.cloud.bigtable.config.BigtableOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.core.IBigtableDataClient;
 import com.google.cloud.bigtable.data.v2.models.KeyOffset;
 import com.google.cloud.bigtable.grpc.BigtableTableName;
 import com.google.cloud.bigtable.hbase.adapters.SampledRowKeysAdapter;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.util.List;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/AbstractBigtableTable.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/AbstractBigtableTable.java
index de9c420db..1d44e4fd8 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/AbstractBigtableTable.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/AbstractBigtableTable.java
@@ -17,7 +17,6 @@ package com.google.cloud.bigtable.hbase;
 
 import com.google.api.core.InternalApi;
 import com.google.cloud.bigtable.config.BigtableOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.core.IBigtableDataClient;
 import com.google.cloud.bigtable.data.v2.models.ConditionalRowMutation;
 import com.google.cloud.bigtable.data.v2.models.ReadModifyWriteRow;
@@ -28,6 +27,7 @@ import com.google.cloud.bigtable.hbase.adapters.Adapters;
 import com.google.cloud.bigtable.hbase.adapters.CheckAndMutateUtil;
 import com.google.cloud.bigtable.hbase.adapters.HBaseRequestAdapter;
 import com.google.cloud.bigtable.hbase.adapters.read.GetAdapter;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.cloud.bigtable.metrics.BigtableClientMetrics;
 import com.google.cloud.bigtable.metrics.BigtableClientMetrics.MetricLevel;
 import com.google.cloud.bigtable.metrics.Timer;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BatchExecutor.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BatchExecutor.java
index 16a660e60..04665bc08 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BatchExecutor.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BatchExecutor.java
@@ -21,12 +21,12 @@ import com.google.api.core.ApiFutures;
 import com.google.api.core.InternalApi;
 import com.google.api.core.SettableApiFuture;
 import com.google.cloud.bigtable.config.BigtableOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.grpc.BigtableSession;
 import com.google.cloud.bigtable.grpc.async.BulkRead;
 import com.google.cloud.bigtable.grpc.scanner.FlatRow;
 import com.google.cloud.bigtable.hbase.adapters.Adapters;
 import com.google.cloud.bigtable.hbase.adapters.HBaseRequestAdapter;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.cloud.bigtable.metrics.BigtableClientMetrics;
 import com.google.cloud.bigtable.metrics.BigtableClientMetrics.MetricLevel;
 import com.google.cloud.bigtable.metrics.Timer;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableBufferedMutator.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableBufferedMutator.java
index f25c80cd8..a28fc5078 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableBufferedMutator.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableBufferedMutator.java
@@ -19,9 +19,9 @@ import com.google.api.core.ApiFuture;
 import com.google.api.core.ApiFutureCallback;
 import com.google.api.core.ApiFutures;
 import com.google.api.core.InternalApi;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.grpc.BigtableSession;
 import com.google.cloud.bigtable.hbase.adapters.HBaseRequestAdapter;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.io.IOException;
 import java.util.ArrayList;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableBufferedMutatorHelper.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableBufferedMutatorHelper.java
index b39713f37..ba9f02cd9 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableBufferedMutatorHelper.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableBufferedMutatorHelper.java
@@ -19,13 +19,13 @@ import com.google.api.core.ApiFuture;
 import com.google.api.core.ApiFutures;
 import com.google.api.core.InternalApi;
 import com.google.cloud.bigtable.config.BigtableOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.core.IBigtableDataClient;
 import com.google.cloud.bigtable.core.IBulkMutation;
 import com.google.cloud.bigtable.grpc.BigtableSession;
 import com.google.cloud.bigtable.grpc.BigtableTableName;
 import com.google.cloud.bigtable.grpc.async.OperationAccountant;
 import com.google.cloud.bigtable.hbase.adapters.HBaseRequestAdapter;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.cloud.bigtable.util.ApiFutureUtil;
 import java.io.IOException;
 import java.util.ArrayList;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableExtendedScan.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableExtendedScan.java
index eab029934..74f8c2a54 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableExtendedScan.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableExtendedScan.java
@@ -19,7 +19,7 @@ import com.google.api.core.InternalExtensionOnly;
 import com.google.bigtable.v2.RowRange;
 import com.google.bigtable.v2.RowSet;
 import com.google.cloud.bigtable.hbase.util.ByteStringer;
-import com.google.cloud.bigtable.util.RowKeyUtil;
+import com.google.cloud.bigtable.hbase.util.RowKeyUtil;
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.hadoop.hbase.client.Table;
 
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableOptionsFactory.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableOptionsFactory.java
index 5c196ead5..8e696bbac 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableOptionsFactory.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableOptionsFactory.java
@@ -31,8 +31,8 @@ import com.google.cloud.bigtable.config.BigtableOptions;
 import com.google.cloud.bigtable.config.BulkOptions;
 import com.google.cloud.bigtable.config.CallOptionsConfig;
 import com.google.cloud.bigtable.config.CredentialOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.config.RetryOptions;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.common.base.Preconditions;
 import io.grpc.Status;
 import java.io.FileInputStream;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableRegionLocator.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableRegionLocator.java
index 6fb0e22e1..16318cc8a 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableRegionLocator.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/BigtableRegionLocator.java
@@ -17,8 +17,8 @@ package com.google.cloud.bigtable.hbase;
 
 import com.google.api.core.InternalApi;
 import com.google.cloud.bigtable.config.BigtableOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.core.IBigtableDataClient;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import java.io.IOException;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/CheckConfig.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/CheckConfig.java
index a787fcb0b..ee30c5186 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/CheckConfig.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/CheckConfig.java
@@ -20,7 +20,7 @@ import com.google.api.core.InternalExtensionOnly;
 import com.google.auth.Credentials;
 import com.google.cloud.bigtable.config.BigtableOptions;
 import com.google.cloud.bigtable.config.CredentialFactory;
-import com.google.cloud.bigtable.config.Logger;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.common.base.Strings;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/SampledRowKeysAdapter.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/SampledRowKeysAdapter.java
index 288adaf68..14f4eaca9 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/SampledRowKeysAdapter.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/SampledRowKeysAdapter.java
@@ -16,8 +16,8 @@
 package com.google.cloud.bigtable.hbase.adapters;
 
 import com.google.api.core.InternalApi;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.data.v2.models.KeyOffset;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.hadoop.hbase.HConstants;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/filters/PrefixFilterAdapter.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/filters/PrefixFilterAdapter.java
index 1501d93bc..620359424 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/filters/PrefixFilterAdapter.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/filters/PrefixFilterAdapter.java
@@ -20,7 +20,7 @@ import static com.google.cloud.bigtable.data.v2.models.Filters.FILTERS;
 import com.google.api.core.InternalApi;
 import com.google.cloud.bigtable.data.v2.models.Filters.Filter;
 import com.google.cloud.bigtable.hbase.adapters.read.ReaderExpressionHelper;
-import com.google.cloud.bigtable.util.RowKeyUtil;
+import com.google.cloud.bigtable.hbase.util.RowKeyUtil;
 import com.google.cloud.bigtable.util.RowKeyWrapper;
 import com.google.common.collect.ImmutableRangeSet;
 import com.google.common.collect.Range;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/read/RowCell.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/read/RowCell.java
index 46d488b31..3c4f47a4f 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/read/RowCell.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/adapters/read/RowCell.java
@@ -14,6 +14,8 @@
 package com.google.cloud.bigtable.hbase.adapters.read;
 
 import com.google.api.core.InternalApi;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.CellComparator;
 import org.apache.hadoop.hbase.HConstants;
@@ -22,11 +24,12 @@ import org.apache.hadoop.hbase.KeyValue.Type;
 import org.apache.hadoop.hbase.util.Bytes;
 
 /**
- * This implementation of {@link org.apache.hadoop.hbase.Cell} is more efficient for Bigtable
- * scanning than {@link org.apache.hadoop.hbase.KeyValue} . RowCell is pretty straight forward. Each
- * *Array() method returns the array passed in in the constructor. Each *Offset() method returns 0.
- * Each *Length() returns the length of the array. This implementation is a few microseconds quicker
- * thank KeyValue, which makes a big performance difference for large scans.
+ * RowCell is an alternative implementation of {@link KeyValue}. Unlike KeyValue, RowCell stores
+ * each value separately, which minimizes the number of copies that need to be made when unpacking
+ * the results from the Cloud Bigtable api.
+ *
+ * <p>This implementation is a few microseconds quicker than KeyValue, which makes a big performance
+ * difference for large scans.
  *
  * <p>For internal use only - public for technical reasons.
  */
@@ -38,6 +41,7 @@ public class RowCell implements Cell {
   private final byte[] qualifierArray;
   private final long timestamp;
   private final byte[] valueArray;
+  private final List<String> labels;
 
   /**
    * Constructor for RowCell.
@@ -54,11 +58,32 @@ public class RowCell implements Cell {
       byte[] qualifierArray,
       long timestamp,
       byte[] valueArray) {
+    this(rowArray, familyArray, qualifierArray, timestamp, valueArray, ImmutableList.<String>of());
+  }
+
+  /**
+   * Constructor for RowCell.
+   *
+   * @param rowArray an array of byte.
+   * @param familyArray an array of byte.
+   * @param qualifierArray an array of byte.
+   * @param timestamp a long.
+   * @param valueArray an array of byte.
+   * @param labels a list of string labels.
+   */
+  public RowCell(
+      byte[] rowArray,
+      byte[] familyArray,
+      byte[] qualifierArray,
+      long timestamp,
+      byte[] valueArray,
+      List<String> labels) {
     this.rowArray = rowArray;
     this.familyArray = familyArray;
     this.qualifierArray = qualifierArray;
     this.timestamp = timestamp;
     this.valueArray = valueArray;
+    this.labels = labels;
   }
 
   /** {@inheritDoc} */
@@ -204,6 +229,15 @@ public class RowCell implements Cell {
     return Bytes.copy(this.rowArray);
   }
 
+  /**
+   * Internal labels that were applied by a transformer filter. These labels are meant to be
+   * consumed by the bigtable-hbase scanner when implementing adapters like the {@link
+   * com.google.cloud.bigtable.hbase.adapters.filters.WhileMatchFilterAdapter}.
+   */
+  public List<String> getLabels() {
+    return this.labels;
+  }
+
   /** Needed doing 'contains' on List. Only compares the key portion, not the value. */
   @Override
   public boolean equals(Object other) {
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/util/Logger.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/util/Logger.java
new file mode 100644
index 000000000..85a326e6b
--- /dev/null
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/util/Logger.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2020 Google LLC.
+ *
+ * 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.
+ */
+package com.google.cloud.bigtable.hbase.util;
+
+import com.google.api.core.InternalApi;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Wrapper around {@link Log} to conditionally format messages if a specified log level is enabled.
+ *
+ * <p>For internal use only - public for technical reasons.
+ */
+@InternalApi("For internal usage only")
+public class Logger {
+  protected final Log log;
+
+  /**
+   * Constructor for Logger.
+   *
+   * @param logClass a {@link Class} object.
+   */
+  public Logger(Class<?> logClass) {
+    this.log = LogFactory.getLog(logClass);
+  }
+
+  /**
+   * trace
+   *
+   * @see Log#trace
+   * @param message Format string.
+   * @param args Arguments for format string.
+   */
+  public void trace(String message, Object... args) {
+    if (log.isTraceEnabled()) {
+      log.trace(String.format(message, args));
+    }
+  }
+
+  /**
+   * debug
+   *
+   * @see Log#debug
+   * @param message Format string.
+   * @param args Arguments for format string.
+   */
+  public void debug(String message, Object... args) {
+    if (log.isDebugEnabled()) {
+      log.debug(String.format(message, args));
+    }
+  }
+
+  /**
+   * debug
+   *
+   * @see Log#debug
+   * @param message Format string.
+   * @param t a {@link Throwable} object.
+   * @param args Arguments for format string.
+   */
+  public void debug(String message, Throwable t, Object... args) {
+    if (log.isDebugEnabled()) {
+      log.debug(String.format(message, args), t);
+    }
+  }
+
+  /**
+   * info
+   *
+   * @see Log#info
+   * @param message Format string.
+   * @param args Arguments for format string.
+   */
+  public void info(String message, Object... args) {
+    if (log.isInfoEnabled()) {
+      log.info(String.format(message, args));
+    }
+  }
+
+  /**
+   * info
+   *
+   * @see Log#info
+   * @param message Format string.
+   * @param t a {@link Throwable} object.
+   * @param args Arguments for format string.
+   */
+  public void info(String message, Throwable t, Object... args) {
+    if (log.isInfoEnabled()) {
+      log.info(String.format(message, args), t);
+    }
+  }
+
+  /**
+   * warn
+   *
+   * @see Log#warn
+   * @param message Format string.
+   * @param args Arguments for format string.
+   */
+  public void warn(String message, Object... args) {
+    if (log.isWarnEnabled()) {
+      log.warn(String.format(message, args));
+    }
+  }
+
+  /**
+   * warn
+   *
+   * @see Log#warn
+   * @param message Format string.
+   * @param t a {@link Throwable} object.
+   * @param args Arguments for format string.
+   */
+  public void warn(String message, Throwable t, Object... args) {
+    if (log.isWarnEnabled()) {
+      log.warn(String.format(message, args), t);
+    }
+  }
+
+  /**
+   * error
+   *
+   * @see Log#error
+   * @param message Format string.
+   * @param args Arguments for format string.
+   */
+  public void error(String message, Object... args) {
+    if (log.isErrorEnabled()) {
+      log.error(String.format(message, args));
+    }
+  }
+
+  /**
+   * error
+   *
+   * @see Log#error
+   * @param message Format string.
+   * @param t a {@link Throwable} object.
+   * @param args Arguments for format string.
+   */
+  public void error(String message, Throwable t, Object... args) {
+    if (log.isErrorEnabled()) {
+      log.error(String.format(message, args), t);
+    }
+  }
+
+  /**
+   * fatal
+   *
+   * @see Log#fatal
+   * @param message a {@link String} object.
+   * @param args a {@link Object} object.
+   */
+  public void fatal(String message, Object... args) {
+    if (log.isFatalEnabled()) {
+      log.fatal(String.format(message, args));
+    }
+  }
+
+  /**
+   * fatal
+   *
+   * @see Log#fatal
+   * @param message Format string.
+   * @param t a {@link Throwable} object.
+   * @param args Arguments for format string.
+   */
+  public void fatal(String message, Throwable t, Object... args) {
+    if (log.isFatalEnabled()) {
+      log.fatal(String.format(message, args), t);
+    }
+  }
+
+  /** Get the underlying {@link Log} */
+  public Log getLog() {
+    return log;
+  }
+}
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/util/RowKeyUtil.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/util/RowKeyUtil.java
new file mode 100644
index 000000000..d154a493d
--- /dev/null
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/com/google/cloud/bigtable/hbase/util/RowKeyUtil.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2020 Google LLC.
+ *
+ * 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.
+ */
+package com.google.cloud.bigtable.hbase.util;
+
+import com.google.api.core.InternalApi;
+import java.util.Arrays;
+
+/** For internal use only - public for technical reasons. */
+@InternalApi
+public class RowKeyUtil {
+  private static final byte[] EMPTY_KEY = new byte[0];
+  /**
+   * When scanning for a prefix the scan should stop immediately after the the last row that has the
+   * specified prefix. This method calculates the closest next rowKey immediately following the
+   * given rowKeyPrefix.
+   *
+   * <p><b>IMPORTANT: This converts a rowKey<u>Prefix</u> into a rowKey</b>.
+   *
+   * <p>If the prefix is an 'ASCII' string put into a byte[] then this is easy because you can
+   * simply increment the last byte of the array. But if your application uses real binary rowids
+   * you may run into the scenario that your prefix is something like: &nbsp;&nbsp;&nbsp;<b>{ 0x12,
+   * 0x23, 0xFF, 0xFF }</b><br>
+   * Then this stopRow needs to be fed into the actual scan<br>
+   * &nbsp;&nbsp;&nbsp;<b>{ 0x12, 0x24 }</b> (Notice that it is shorter now)<br>
+   * This method calculates the correct stop row value for this usecase.
+   *
+   * @param rowKeyPrefix the rowKey<u>Prefix</u>.
+   * @return the closest next rowKey immediately following the given rowKeyPrefix.
+   */
+  public static byte[] calculateTheClosestNextRowKeyForPrefix(byte[] rowKeyPrefix) {
+    // Essentially we are treating it like an 'unsigned very very long' and doing +1 manually.
+    // Search for the place where the trailing 0xFFs start
+    int offset = rowKeyPrefix.length;
+    while (offset > 0) {
+      if (rowKeyPrefix[offset - 1] != (byte) 0xFF) {
+        break;
+      }
+      offset--;
+    }
+
+    if (offset == 0) {
+      // We got an 0xFFFF... (only FFs) stopRow value which is
+      // the last possible prefix before the end of the table.
+      // So set it to stop at the 'end of the table'
+      return EMPTY_KEY;
+    }
+
+    // Copy the right length of the original
+    byte[] newStopRow = Arrays.copyOfRange(rowKeyPrefix, 0, offset);
+    // And increment the last one
+    newStopRow[newStopRow.length - 1]++;
+    return newStopRow;
+  }
+}
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableAdmin.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableAdmin.java
index 953fc0e21..c5ae76f28 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableAdmin.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableAdmin.java
@@ -29,12 +29,12 @@ import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest;
 import com.google.cloud.bigtable.admin.v2.models.ModifyColumnFamiliesRequest;
 import com.google.cloud.bigtable.admin.v2.models.Table;
 import com.google.cloud.bigtable.config.BigtableOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.core.IBigtableTableAdminClient;
 import com.google.cloud.bigtable.grpc.BigtableClusterName;
 import com.google.cloud.bigtable.grpc.BigtableInstanceName;
 import com.google.cloud.bigtable.hbase.BigtableOptionsFactory;
 import com.google.cloud.bigtable.hbase.adapters.admin.TableAdapter;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.cloud.bigtable.hbase.util.ModifyTableBuilder;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableConnection.java b/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableConnection.java
index cac4ba5c6..618a9f9d7 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableConnection.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/main/java/org/apache/hadoop/hbase/client/AbstractBigtableConnection.java
@@ -18,7 +18,6 @@ package org.apache.hadoop.hbase.client;
 
 import com.google.api.core.InternalApi;
 import com.google.cloud.bigtable.config.BigtableOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.grpc.BigtableSession;
 import com.google.cloud.bigtable.hbase.BigtableBufferedMutator;
 import com.google.cloud.bigtable.hbase.BigtableOptionsFactory;
@@ -27,6 +26,7 @@ import com.google.cloud.bigtable.hbase.adapters.Adapters;
 import com.google.cloud.bigtable.hbase.adapters.HBaseRequestAdapter;
 import com.google.cloud.bigtable.hbase.adapters.HBaseRequestAdapter.MutationAdapters;
 import com.google.cloud.bigtable.hbase.adapters.SampledRowKeysAdapter;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.common.base.MoreObjects;
 import java.io.Closeable;
 import java.io.IOException;
diff --git a/bigtable-client-core-parent/pom.xml b/bigtable-client-core-parent/pom.xml
index 8e492d6e7..9da1c4020 100644
--- a/bigtable-client-core-parent/pom.xml
+++ b/bigtable-client-core-parent/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-client-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-client-core-parent</artifactId>
diff --git a/bigtable-dataflow-parent/bigtable-beam-import/pom.xml b/bigtable-dataflow-parent/bigtable-beam-import/pom.xml
index 31dd3658e..55402c0db 100644
--- a/bigtable-dataflow-parent/bigtable-beam-import/pom.xml
+++ b/bigtable-dataflow-parent/bigtable-beam-import/pom.xml
@@ -14,13 +14,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-dataflow-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
@@ -241,8 +239,7 @@ limitations under the License.
         <configuration>
           <shadedArtifactAttached>true</shadedArtifactAttached>
           <transformers>
-            <transformer
-                implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+            <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
           </transformers>
         </configuration>
       </plugin>
diff --git a/bigtable-dataflow-parent/bigtable-hbase-beam/pom.xml b/bigtable-dataflow-parent/bigtable-hbase-beam/pom.xml
index 7b6512a41..f9763deab 100755
--- a/bigtable-dataflow-parent/bigtable-hbase-beam/pom.xml
+++ b/bigtable-dataflow-parent/bigtable-hbase-beam/pom.xml
@@ -10,15 +10,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-dataflow-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-hbase-beam</artifactId>
diff --git a/bigtable-dataflow-parent/bigtable-hbase-beam/src/main/java/com/google/cloud/bigtable/beam/CloudBigtableIO.java b/bigtable-dataflow-parent/bigtable-hbase-beam/src/main/java/com/google/cloud/bigtable/beam/CloudBigtableIO.java
index f98d8b79d..098204e77 100755
--- a/bigtable-dataflow-parent/bigtable-hbase-beam/src/main/java/com/google/cloud/bigtable/beam/CloudBigtableIO.java
+++ b/bigtable-dataflow-parent/bigtable-hbase-beam/src/main/java/com/google/cloud/bigtable/beam/CloudBigtableIO.java
@@ -163,7 +163,8 @@ public class CloudBigtableIO {
     protected List<SourceWithKeys> getSplits(long desiredBundleSizeBytes) throws Exception {
       desiredBundleSizeBytes =
           Math.max(
-              getEstimatedSizeBytes(null) / SIZED_BASED_MAX_SPLIT_COUNT, desiredBundleSizeBytes);
+              calculateEstimatedSizeBytes(null) / SIZED_BASED_MAX_SPLIT_COUNT,
+              desiredBundleSizeBytes);
       CloudBigtableScanConfiguration conf = getConfiguration();
       byte[] scanStartKey = conf.getZeroCopyStartRow();
       byte[] scanEndKey = conf.getZeroCopyStopRow();
@@ -301,6 +302,16 @@ public class CloudBigtableIO {
      */
     @Override
     public long getEstimatedSizeBytes(PipelineOptions options) throws IOException {
+      try {
+        return calculateEstimatedSizeBytes(options);
+        // When using templates, we can't estimate the source size because we can't pull out the
+        // source table. So we return unknown (0L).
+      } catch (IllegalStateException e) {
+        return 0;
+      }
+    }
+
+    protected long calculateEstimatedSizeBytes(PipelineOptions options) throws IOException {
       long totalEstimatedSizeBytes = 0;
 
       byte[] scanStartKey = getConfiguration().getZeroCopyStartRow();
@@ -444,43 +455,6 @@ public class CloudBigtableIO {
       return splits;
     }
 
-    /**
-     * Gets an estimated size based on data returned from {@link
-     * CloudBigtableServiceImpl#getSampleRowKeys(CloudBigtableTableConfiguration)}. The estimate
-     * will be high if a {@link Scan} is set on the {@link CloudBigtableScanConfiguration}; in such
-     * cases, the estimate will not take the Scan into account, and will return a larger estimate
-     * than what the {@link CloudBigtableIO.Reader} will actually read.
-     *
-     * @param options The pipeline options.
-     * @return The estimated size of the data, in bytes.
-     */
-    @Override
-    public long getEstimatedSizeBytes(PipelineOptions options) throws IOException {
-      long totalEstimatedSizeBytes = 0;
-
-      byte[] scanStartKey = getConfiguration().getZeroCopyStartRow();
-      byte[] scanEndKey = getConfiguration().getZeroCopyStopRow();
-
-      byte[] startKey = HConstants.EMPTY_START_ROW;
-      long lastOffset = 0;
-      for (KeyOffset response : getSampleRowKeys()) {
-        byte[] currentEndKey = response.getKey().toByteArray();
-        // Avoid empty regions.
-        if (Bytes.equals(startKey, currentEndKey) && startKey.length != 0) {
-          continue;
-        }
-        long offset = response.getOffsetBytes();
-        if (isWithinRange(scanStartKey, scanEndKey, startKey, currentEndKey)) {
-          totalEstimatedSizeBytes += (offset - lastOffset);
-        }
-        lastOffset = offset;
-        startKey = currentEndKey;
-      }
-      SOURCE_LOG.info("Estimated size in bytes: " + totalEstimatedSizeBytes);
-
-      return totalEstimatedSizeBytes;
-    }
-
     @Override
     public Coder<Result> getOutputCoder() {
       return getResultCoder();
@@ -520,18 +494,8 @@ public class CloudBigtableIO {
       SOURCE_LOG.debug("Source with split: {}.", this);
     }
 
-    /**
-     * Gets an estimate of the size of the source.
-     *
-     * <p>NOTE: This value is a guesstimate. It could be significantly off, especially if there is
-     * a{@link Scan} selected in the configuration. It will also be off if the start and stop keys
-     * are calculated via {@link Source#split(long, PipelineOptions)}.
-     *
-     * @param options The pipeline options.
-     * @return The estimated size of the source, in bytes.
-     */
     @Override
-    public long getEstimatedSizeBytes(PipelineOptions options) {
+    protected long calculateEstimatedSizeBytes(PipelineOptions options) throws IOException {
       return estimatedSize;
     }
 
@@ -672,7 +636,7 @@ public class CloudBigtableIO {
 
       long estimatedSizeBytes = -1;
       try {
-        estimatedSizeBytes = source.getEstimatedSizeBytes(null);
+        estimatedSizeBytes = source.calculateEstimatedSizeBytes(null);
       } catch (IOException e) {
         READER_LOG.info(
             "{}: Failed to get estimated size for key for fraction {}.",
diff --git a/bigtable-dataflow-parent/pom.xml b/bigtable-dataflow-parent/pom.xml
index b8a805010..b2062c0ae 100644
--- a/bigtable-dataflow-parent/pom.xml
+++ b/bigtable-dataflow-parent/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-client-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-dataflow-parent</artifactId>
diff --git a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-benchmarks/pom.xml b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-benchmarks/pom.xml
index d21df6fb6..f128abf6d 100644
--- a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-benchmarks/pom.xml
+++ b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-benchmarks/pom.xml
@@ -1,11 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <parent>
     <artifactId>bigtable-hbase-1.x-parent</artifactId>
     <groupId>com.google.cloud.bigtable</groupId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
@@ -74,12 +72,10 @@
                 </filter>
               </filters>
               <transformers>
-                <transformer
-                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                   <mainClass>org.openjdk.jmh.Main</mainClass>
                 </transformer>
-                <transformer
-                    implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
               </transformers>
             </configuration>
           </execution>
diff --git a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-hadoop/pom.xml b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-hadoop/pom.xml
index ac2d28194..d2f57179c 100644
--- a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-hadoop/pom.xml
+++ b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-hadoop/pom.xml
@@ -14,13 +14,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <parent>
     <artifactId>bigtable-hbase-1.x-parent</artifactId>
     <groupId>com.google.cloud.bigtable</groupId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-mapreduce/pom.xml b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-mapreduce/pom.xml
index 4cd448abc..d663617ca 100644
--- a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-mapreduce/pom.xml
+++ b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-mapreduce/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-hbase-1.x-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-hbase-1.x-mapreduce</artifactId>
diff --git a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-shaded/pom.xml b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-shaded/pom.xml
index 6f0f1f3e8..7bde43c42 100644
--- a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-shaded/pom.xml
+++ b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-shaded/pom.xml
@@ -14,13 +14,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <parent>
     <artifactId>bigtable-hbase-1.x-parent</artifactId>
     <groupId>com.google.cloud.bigtable</groupId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
@@ -132,8 +130,7 @@ limitations under the License.
                 </filter>
               </filters>
               <transformers>
-                <transformer
-                    implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
               </transformers>
               <artifactSet>
                 <excludes>
diff --git a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x/pom.xml b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x/pom.xml
index dacde8bd1..a0e470b7c 100644
--- a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x/pom.xml
+++ b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-hbase-1.x-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-hbase-1.x</artifactId>
diff --git a/bigtable-hbase-1.x-parent/pom.xml b/bigtable-hbase-1.x-parent/pom.xml
index d89e40f05..0c45076c3 100644
--- a/bigtable-hbase-1.x-parent/pom.xml
+++ b/bigtable-hbase-1.x-parent/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-client-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-hbase-1.x-parent</artifactId>
@@ -72,7 +70,7 @@ limitations under the License.
               <overview>../overview.html</overview>
               <bottom><![CDATA[<br>]]></bottom>
 
-              <detectLinks/>
+              <detectLinks />
               <links>
                 <link>https://hbase.apache.org/apidocs/</link>
                 <link>http://www.grpc.io/grpc-java/javadoc/</link>
diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-hadoop/pom.xml b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-hadoop/pom.xml
index 4a101364f..824cb7b97 100644
--- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-hadoop/pom.xml
+++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-hadoop/pom.xml
@@ -14,13 +14,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <parent>
     <artifactId>bigtable-hbase-2.x-parent</artifactId>
     <groupId>com.google.cloud.bigtable</groupId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-shaded/pom.xml b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-shaded/pom.xml
index 08d7806de..cb73e2a6d 100644
--- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-shaded/pom.xml
+++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-shaded/pom.xml
@@ -14,13 +14,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <parent>
     <artifactId>bigtable-hbase-2.x-parent</artifactId>
     <groupId>com.google.cloud.bigtable</groupId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
@@ -137,8 +135,7 @@ limitations under the License.
                 false
               </promoteTransitiveDependencies>
               <transformers>
-                <transformer
-                    implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
               </transformers>
               <filters>
                 <filter>
diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/pom.xml b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/pom.xml
index c757e5df9..a9465cf66 100644
--- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/pom.xml
+++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-hbase-2.x-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <properties>
diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncAdmin.java b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncAdmin.java
index a6f2cf7b8..6d0a15bec 100644
--- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncAdmin.java
+++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncAdmin.java
@@ -27,11 +27,11 @@ import com.google.bigtable.admin.v2.SnapshotTableRequest;
 import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest;
 import com.google.cloud.bigtable.admin.v2.models.Table;
 import com.google.cloud.bigtable.config.BigtableOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.core.IBigtableTableAdminClient;
 import com.google.cloud.bigtable.grpc.BigtableClusterName;
 import com.google.cloud.bigtable.grpc.BigtableInstanceName;
 import com.google.cloud.bigtable.hbase.BigtableOptionsFactory;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.cloud.bigtable.hbase.util.ModifyTableBuilder;
 import com.google.cloud.bigtable.hbase2_x.adapters.admin.TableAdapter2x;
 import com.google.common.base.Preconditions;
diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncTable.java b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncTable.java
index eec6726ee..78f899033 100644
--- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncTable.java
+++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAsyncTable.java
@@ -19,7 +19,6 @@ import static com.google.cloud.bigtable.hbase2_x.FutureUtils.toCompletableFuture
 import static java.util.stream.Collectors.toList;
 
 import com.google.api.core.InternalApi;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.core.IBigtableDataClient;
 import com.google.cloud.bigtable.data.v2.models.ConditionalRowMutation;
 import com.google.cloud.bigtable.data.v2.models.Query;
@@ -30,6 +29,7 @@ import com.google.cloud.bigtable.hbase.adapters.Adapters;
 import com.google.cloud.bigtable.hbase.adapters.CheckAndMutateUtil;
 import com.google.cloud.bigtable.hbase.adapters.HBaseRequestAdapter;
 import com.google.cloud.bigtable.hbase.adapters.read.GetAdapter;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.common.base.Preconditions;
 import io.grpc.stub.StreamObserver;
 import io.opencensus.common.Scope;
diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/FutureUtils.java b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/FutureUtils.java
index 658f4f004..c6c478eff 100644
--- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/FutureUtils.java
+++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/FutureUtils.java
@@ -19,7 +19,7 @@ import com.google.api.core.ApiFuture;
 import com.google.api.core.ApiFutureCallback;
 import com.google.api.core.ApiFutures;
 import com.google.api.core.InternalApi;
-import com.google.cloud.bigtable.config.Logger;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/org/apache/hadoop/hbase/client/BigtableAsyncConnection.java b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/org/apache/hadoop/hbase/client/BigtableAsyncConnection.java
index a0d4b7ec0..822f12c7a 100644
--- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/org/apache/hadoop/hbase/client/BigtableAsyncConnection.java
+++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/org/apache/hadoop/hbase/client/BigtableAsyncConnection.java
@@ -18,7 +18,6 @@ package org.apache.hadoop.hbase.client;
 import com.google.api.core.InternalApi;
 import com.google.bigtable.v2.SampleRowKeysRequest;
 import com.google.cloud.bigtable.config.BigtableOptions;
-import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.data.v2.models.KeyOffset;
 import com.google.cloud.bigtable.grpc.BigtableSession;
 import com.google.cloud.bigtable.hbase.BigtableOptionsFactory;
@@ -26,6 +25,7 @@ import com.google.cloud.bigtable.hbase.adapters.Adapters;
 import com.google.cloud.bigtable.hbase.adapters.HBaseRequestAdapter;
 import com.google.cloud.bigtable.hbase.adapters.HBaseRequestAdapter.MutationAdapters;
 import com.google.cloud.bigtable.hbase.adapters.SampledRowKeysAdapter;
+import com.google.cloud.bigtable.hbase.util.Logger;
 import com.google.cloud.bigtable.hbase2_x.BigtableAsyncAdmin;
 import com.google.cloud.bigtable.hbase2_x.BigtableAsyncBufferedMutator;
 import com.google.cloud.bigtable.hbase2_x.BigtableAsyncTable;
diff --git a/bigtable-hbase-2.x-parent/pom.xml b/bigtable-hbase-2.x-parent/pom.xml
index 6437f753d..7b69f78ea 100644
--- a/bigtable-hbase-2.x-parent/pom.xml
+++ b/bigtable-hbase-2.x-parent/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-client-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-hbase-2.x-parent</artifactId>
@@ -70,7 +68,7 @@ limitations under the License.
               <overview>../overview.html</overview>
               <bottom><![CDATA[<br>]]></bottom>
 
-              <detectLinks/>
+              <detectLinks />
               <links>
                 <link>https://hbase.apache.org/apidocs/</link>
                 <link>http://www.grpc.io/grpc-java/javadoc/</link>
diff --git a/pom.xml b/pom.xml
index b03a41b3e..b5fa54331 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,14 +14,12 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <groupId>com.google.cloud.bigtable</groupId>
   <artifactId>bigtable-client-parent</artifactId>
-  <version>1.13.1-SNAPSHOT</version>
+  <version>1.14.1-SNAPSHOT</version>
   <packaging>pom</packaging>
   <name>${project.groupId}:${project.artifactId}</name>
   <url>https://cloud.google.com/bigtable/</url>
@@ -52,7 +50,7 @@ limitations under the License.
     <compileSource.1.8>1.8</compileSource.1.8>
 
     <!-- core dependency versions -->
-    <bigtable.version>1.10.0</bigtable.version>
+    <bigtable.version>1.11.0</bigtable.version>
     <dropwizard.metrics.version>3.2.6</dropwizard.metrics.version>
     <slf4j.version>1.7.30</slf4j.version>
     <commons-logging.version>1.2</commons-logging.version>


Test patch:
diff --git a/bigtable-client-core-parent/bigtable-hbase-integration-tests-common/pom.xml b/bigtable-client-core-parent/bigtable-hbase-integration-tests-common/pom.xml
index 5275634e1..3217a29ee 100644
--- a/bigtable-client-core-parent/bigtable-hbase-integration-tests-common/pom.xml
+++ b/bigtable-client-core-parent/bigtable-hbase-integration-tests-common/pom.xml
@@ -14,14 +14,12 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-client-core-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-hbase-integration-tests-common</artifactId>
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/read/TestRowCell.java b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/read/TestRowCell.java
index ff5aca076..89218dbf1 100644
--- a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/read/TestRowCell.java
+++ b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/adapters/read/TestRowCell.java
@@ -14,7 +14,9 @@
 package com.google.cloud.bigtable.hbase.adapters.read;
 
 import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.hasItems;
 
+import java.util.Arrays;
 import org.hamcrest.MatcherAssert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -39,4 +41,18 @@ public class TestRowCell {
     MatcherAssert.assertThat(result, containsString("qualifier"));
     MatcherAssert.assertThat(result, containsString("1487963474314"));
   }
+
+  @Test
+  public void testLabels() {
+    RowCell rowCell =
+        new RowCell(
+            "mykey".getBytes(),
+            "myfamily".getBytes(),
+            "myqualifier".getBytes(),
+            100000L,
+            "myvalue".getBytes(),
+            Arrays.asList("First-label", "Second-label"));
+
+    MatcherAssert.assertThat(rowCell.getLabels(), hasItems("First-label", "Second-label"));
+  }
 }
diff --git a/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/util/RowKeyUtilTest.java b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/util/RowKeyUtilTest.java
new file mode 100644
index 000000000..8824527a3
--- /dev/null
+++ b/bigtable-client-core-parent/bigtable-hbase/src/test/java/com/google/cloud/bigtable/hbase/util/RowKeyUtilTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 Google LLC.
+ *
+ * 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.
+ */
+package com.google.cloud.bigtable.hbase.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class RowKeyUtilTest {
+
+  @Test
+  public void test_simple() {
+    byte[] key = "test".getBytes();
+    byte[] nextKey = RowKeyUtil.calculateTheClosestNextRowKeyForPrefix(key);
+    Assert.assertEquals((byte) (key[key.length - 1] + 1), nextKey[key.length - 1]);
+  }
+
+  @Test
+  public void test_unsignedRange() {
+    byte[] key = new byte[] {0x7f};
+    byte[] nextKey = RowKeyUtil.calculateTheClosestNextRowKeyForPrefix(key);
+    Assert.assertEquals((byte) 0x80, nextKey[0]);
+  }
+
+  @Test
+  public void test_trailing0xFF() {
+    byte trailer = (byte) 0xFF;
+    byte[] key = new byte[] {0x01, trailer, trailer, trailer};
+    byte[] nextKey = RowKeyUtil.calculateTheClosestNextRowKeyForPrefix(key);
+    Assert.assertEquals((byte) 0x2, nextKey[0]);
+  }
+}
diff --git a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-integration-tests/pom.xml b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-integration-tests/pom.xml
index d2b842d60..4daa585a6 100644
--- a/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-integration-tests/pom.xml
+++ b/bigtable-hbase-1.x-parent/bigtable-hbase-1.x-integration-tests/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-hbase-1.x-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-hbase-1.x-integration-tests</artifactId>
diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-integration-tests/pom.xml b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-integration-tests/pom.xml
index 44b8d1b45..c8f1ed38d 100644
--- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-integration-tests/pom.xml
+++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x-integration-tests/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.google.cloud.bigtable</groupId>
     <artifactId>bigtable-hbase-2.x-parent</artifactId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-hbase-2.x-integration-tests</artifactId>
diff --git a/bigtable-test/bigtable-emulator-maven-plugin/pom.xml b/bigtable-test/bigtable-emulator-maven-plugin/pom.xml
index e16388913..bcb475646 100644
--- a/bigtable-test/bigtable-emulator-maven-plugin/pom.xml
+++ b/bigtable-test/bigtable-emulator-maven-plugin/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <artifactId>bigtable-test</artifactId>
     <groupId>com.google.cloud.bigtable</groupId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
 
diff --git a/bigtable-test/pom.xml b/bigtable-test/pom.xml
index 018903126..446bacaca 100644
--- a/bigtable-test/pom.xml
+++ b/bigtable-test/pom.xml
@@ -14,15 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project 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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <artifactId>bigtable-client-parent</artifactId>
     <groupId>com.google.cloud.bigtable</groupId>
-    <version>1.13.1-SNAPSHOT</version>
+    <version>1.14.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>bigtable-test</artifactId>