Repository: GoogleCloudPlatform/cloud-bigtable-client
Pull request #2105 (2019-02-20 10:48:32)

Migrated IBigtableTableAdminClient with ApiFuture
- Migrated `IBigtableTableAdminClient` to adapt to ApiFuture.


Patch:
diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/core/IBigtableDataClient.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/core/IBigtableDataClient.java
index ecbfbad64..cede53619 100644
--- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/core/IBigtableDataClient.java
+++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/core/IBigtableDataClient.java
@@ -24,11 +24,9 @@ import com.google.cloud.bigtable.data.v2.models.Row;
 import com.google.cloud.bigtable.data.v2.models.RowMutation;
 import com.google.cloud.bigtable.grpc.scanner.FlatRow;
 import com.google.cloud.bigtable.grpc.scanner.ResultScanner;
-import com.google.common.util.concurrent.ListenableFuture;
 import io.grpc.stub.StreamObserver;
 
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 
 /**
  * Interface to wrap {@link com.google.cloud.bigtable.grpc.BigtableDataClient} with
@@ -47,11 +45,10 @@ public interface IBigtableDataClient {
    * Mutate a row atomically.
    *
    * @param rowMutation a {@link RowMutation} model object.
-   * @return a {@link ListenableFuture} of type {@link Void} will be set when request is
+   * @return a {@link ApiFuture} of type {@link Void} will be set when request is
    *     successful otherwise exception will be thrown.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture<Void> mutateRowAsync(RowMutation rowMutation);
+  ApiFuture<Void> mutateRowAsync(RowMutation rowMutation);
 
   /**
    * Perform an atomic read-modify-write operation on a row.
@@ -65,7 +62,7 @@ public interface IBigtableDataClient {
    * Perform an atomic read-modify-write operation on a row.
    *
    * @param readModifyWriteRow a {@link ReadModifyWriteRow} model object.
-   * @return a {@link ListenableFuture} of type {@link Row} will be set when request is
+   * @return a {@link ApiFuture} of type {@link Row} will be set when request is
    *     successful otherwise exception will be thrown.
    */
   ApiFuture<Row> readModifyWriteRowAsync(ReadModifyWriteRow readModifyWriteRow);
@@ -79,11 +76,10 @@ public interface IBigtableDataClient {
    * Mutate a row atomically dependent on a precondition.
    *
    * @param conditionalRowMutation a {@link ConditionalRowMutation} model object.
-   * @return a {@link ListenableFuture} of type {@link Boolean} will be set when request is
+   * @return a {@link ApiFuture} of type {@link Boolean} will be set when request is
    *     successful otherwise exception will be thrown.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture<Boolean> checkAndMutateRowAsync(ConditionalRowMutation conditionalRowMutation);
+  ApiFuture<Boolean> checkAndMutateRowAsync(ConditionalRowMutation conditionalRowMutation);
 
   /**
    * Mutate a row atomically dependent on a precondition.
@@ -106,10 +102,9 @@ public interface IBigtableDataClient {
    * completed.
    *
    * @param tableId a String object.
-   * @return a {@link ListenableFuture} object.
+   * @return a {@link ApiFuture} object.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture< List<KeyOffset>> sampleRowKeysAsync(String tableId);
+  ApiFuture< List<KeyOffset>> sampleRowKeysAsync(String tableId);
 
   /**
    * Perform a scan over {@link Row}s, in key order.
@@ -122,11 +117,11 @@ public interface IBigtableDataClient {
   /**
    * Read multiple {@link Row}s into an in-memory list, in key order.
    *
-   * @return a {@link ListenableFuture} that will finish when
+   * @return a {@link ApiFuture} that will finish when
    * all reads have completed.
    * @param request a {@link Query} object.
    */
-  ListenableFuture<List<Row>> readRowsAsync(Query request);
+  ApiFuture<List<Row>> readRowsAsync(Query request);
 
   /**
    * Returns a list of {@link FlatRow}s, in key order.
@@ -147,12 +142,11 @@ public interface IBigtableDataClient {
   /**
    * Read multiple {@link FlatRow}s into an in-memory list, in key order.
    *
-   * @return a {@link ListenableFuture} that will finish when
+   * @return a {@link ApiFuture} that will finish when
    * all reads have completed.
    * @param request a {@link Query} object.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture<List<FlatRow>> readFlatRowsAsync(Query request);
+  ApiFuture<List<FlatRow>> readFlatRowsAsync(Query request);
 
   /**
    * Read {@link FlatRow} asynchronously, and pass them to a stream observer to be processed.
diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/core/IBigtableTableAdminClient.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/core/IBigtableTableAdminClient.java
index f5d62e337..a217209dc 100644
--- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/core/IBigtableTableAdminClient.java
+++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/core/IBigtableTableAdminClient.java
@@ -15,6 +15,7 @@
  */
 package com.google.cloud.bigtable.core;
 
+import com.google.api.core.ApiFuture;
 import com.google.bigtable.admin.v2.CreateTableFromSnapshotRequest;
 import com.google.bigtable.admin.v2.DeleteSnapshotRequest;
 import com.google.bigtable.admin.v2.GetSnapshotRequest;
@@ -25,7 +26,6 @@ import com.google.bigtable.admin.v2.SnapshotTableRequest;
 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.common.util.concurrent.ListenableFuture;
 import com.google.longrunning.Operation;
 import java.util.List;
 
@@ -48,8 +48,7 @@ public interface IBigtableTableAdminClient {
    *
    * @param request a {@link CreateTableRequest} object.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture<Table> createTableAsync(CreateTableRequest request);
+  ApiFuture<Table> createTableAsync(CreateTableRequest request);
 
   /**
    * Gets the details of a table.
@@ -62,10 +61,9 @@ public interface IBigtableTableAdminClient {
   /**
    * Gets the details of a table asynchronously.
    *
-   * @return a {@link ListenableFuture} that returns a {@link Table} object.
+   * @return a {@link ApiFuture} that returns a {@link Table} object.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture<Table> getTableAsync(String tableId);
+  ApiFuture<Table> getTableAsync(String tableId);
 
   /**
    * Lists the names of all tables in an instance.
@@ -77,11 +75,10 @@ public interface IBigtableTableAdminClient {
   /**
    * Lists the names of all tables in an instance asynchronously.
    *
-   * @return a {@link ListenableFuture} of type {@link Void} will be set when request is
+   * @return a {@link ApiFuture} of type {@link Void} will be set when request is
    *   successful otherwise exception will be thrown.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture<List<String>> listTablesAsync();
+  ApiFuture<List<String>> listTablesAsync();
 
   /**
    * Permanently deletes a specified table and all of its data.
@@ -92,11 +89,10 @@ public interface IBigtableTableAdminClient {
   /**
    * Permanently deletes a specified table and all of its data.
    *
-   * @return a {@link ListenableFuture} of type {@link Void} will be set when request is
+   * @return a {@link ApiFuture} of type {@link Void} will be set when request is
    *  successful otherwise exception will be thrown.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture<Void> deleteTableAsync(String tableId);
+  ApiFuture<Void> deleteTableAsync(String tableId);
 
   /**
    * Creates, modifies or deletes a new column family within a specified table.
@@ -110,11 +106,10 @@ public interface IBigtableTableAdminClient {
    * Creates, modifies or deletes a new column family within a specified table.
    *
    * @param request a {@link ModifyColumnFamiliesRequest} object.
-   * @return a {@link ListenableFuture} that returns {@link Table} object that contains
+   * @return a {@link ApiFuture} that returns {@link Table} object that contains
    *  the updated table structure.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture<Table> modifyFamiliesAsync(ModifyColumnFamiliesRequest request);
+  ApiFuture<Table> modifyFamiliesAsync(ModifyColumnFamiliesRequest request);
 
   /**
    * Permanently deletes all rows in a range.
@@ -129,10 +124,9 @@ public interface IBigtableTableAdminClient {
    *
    * @param tableId
    * @param rowKeyPrefix
-   * @return a {@link ListenableFuture} that returns {@link Void} object.
+   * @return a {@link ApiFuture} that returns {@link Void} object.
    */
-  //TODO(rahulkql): Once it is adapted to v2.models, change the return type to ApiFuture.
-  ListenableFuture<Void> dropRowRangeAsync(String tableId, String rowKeyPrefix);
+  ApiFuture<Void> dropRowRangeAsync(String tableId, String rowKeyPrefix);
 
   // ////////////// SNAPSHOT methods /////////////
   /**
@@ -140,32 +134,32 @@ public interface IBigtableTableAdminClient {
    * @param request a {@link SnapshotTableRequest} object.
    * @return The long running {@link Operation} for the request.
    */
-  ListenableFuture<Operation> snapshotTableAsync(SnapshotTableRequest request);
+  ApiFuture<Operation> snapshotTableAsync(SnapshotTableRequest request);
 
   /**
    * Gets metadata information about the specified snapshot.
    * @param request a {@link GetSnapshotRequest} object.
    * @return The {@link Snapshot} definied by the request.
    */
-  ListenableFuture<Snapshot> getSnapshotAsync(GetSnapshotRequest request);
+  ApiFuture<Snapshot> getSnapshotAsync(GetSnapshotRequest request);
 
   /**
    * Lists all snapshots associated with the specified cluster.
    * @param request a {@link ListSnapshotsRequest} object.
    * @return The {@link ListSnapshotsResponse} which has the list of the snapshots in the cluster.
    */
-  ListenableFuture<ListSnapshotsResponse> listSnapshotsAsync(ListSnapshotsRequest request);
+  ApiFuture<ListSnapshotsResponse> listSnapshotsAsync(ListSnapshotsRequest request);
 
   /**
    * Permanently deletes the specified snapshot.
    * @param request a {@link DeleteSnapshotRequest} object.
    */
-  ListenableFuture<Void> deleteSnapshotAsync(DeleteSnapshotRequest request);
+  ApiFuture<Void> deleteSnapshotAsync(DeleteSnapshotRequest request);
 
   /**
    * Creates a new table from a snapshot.
    * @param request a {@link CreateTableFromSnapshotRequest} object.
    * @return The long running {@link Operation} for the request.
    */
-  ListenableFuture<Operation> createTableFromSnapshotAsync(CreateTableFromSnapshotRequest request);
+  ApiFuture<Operation> createTableFromSnapshotAsync(CreateTableFromSnapshotRequest request);
 }
diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableDataClientWrapper.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableDataClientWrapper.java
index e31f1a51d..a1343e958 100644
--- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableDataClientWrapper.java
+++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableDataClientWrapper.java
@@ -15,7 +15,9 @@
  */
 package com.google.cloud.bigtable.grpc;
 
+import com.google.api.core.ApiFunction;
 import com.google.api.core.ApiFuture;
+import com.google.api.core.ApiFutures;
 import com.google.bigtable.v2.CheckAndMutateRowRequest;
 import com.google.bigtable.v2.CheckAndMutateRowResponse;
 import com.google.bigtable.v2.MutateRowRequest;
@@ -75,16 +77,16 @@ public class BigtableDataClientWrapper implements IBigtableDataClient {
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<Void> mutateRowAsync(RowMutation rowMutation) {
+  public ApiFuture<Void> mutateRowAsync(RowMutation rowMutation) {
     ListenableFuture<MutateRowResponse> response =
         delegate.mutateRowAsync(rowMutation.toProto(requestContext));
-    return  Futures.transform(response, new Function<MutateRowResponse, Void>() {
+    return  ApiFutureUtil.adapt(Futures.transform(response, new Function<MutateRowResponse, Void>() {
       @Nullable
       @Override
       public Void apply(@Nullable MutateRowResponse mutateRowResponse) {
         return null;
       }
-    }, MoreExecutors.directExecutor());
+    }, MoreExecutors.directExecutor()));
   }
 
   /** {@inheritDoc} */
@@ -116,18 +118,19 @@ public class BigtableDataClientWrapper implements IBigtableDataClient {
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<Boolean> checkAndMutateRowAsync(
+  public ApiFuture<Boolean> checkAndMutateRowAsync(
       ConditionalRowMutation conditionalRowMutation) {
     final CheckAndMutateRowRequest request = conditionalRowMutation.toProto(requestContext);
     final ListenableFuture<CheckAndMutateRowResponse> response =
         delegate.checkAndMutateRowAsync(request);
-    return Futures.transform(response, new Function<CheckAndMutateRowResponse, Boolean>() {
+    return ApiFutureUtil.adapt(Futures.transform(response,
+        new Function<CheckAndMutateRowResponse, Boolean>() {
 
       @Override
       public Boolean apply(CheckAndMutateRowResponse checkAndMutateRowResponse) {
         return checkAndMutateRowResponse.getPredicateMatched();
       }
-    }, MoreExecutors.directExecutor());
+    }, MoreExecutors.directExecutor()));
   }
 
   /** {@inheritDoc} */
@@ -158,7 +161,7 @@ public class BigtableDataClientWrapper implements IBigtableDataClient {
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<List<KeyOffset>> sampleRowKeysAsync(String tableId) {
+  public ApiFuture<List<KeyOffset>> sampleRowKeysAsync(String tableId) {
     String fullTableName = NameUtil
         .formatTableName(requestContext.getProjectId(), requestContext.getInstanceId(), tableId);
     SampleRowKeysRequest requestProto =
@@ -166,7 +169,8 @@ public class BigtableDataClientWrapper implements IBigtableDataClient {
     ListenableFuture<List<SampleRowKeysResponse>> responseProto =
         delegate.sampleRowKeysAsync(requestProto);
 
-    return Futures.transform(responseProto, new Function<List<SampleRowKeysResponse>, List<KeyOffset>>() {
+    return ApiFutureUtil.adapt(Futures
+        .transform(responseProto, new Function<List<SampleRowKeysResponse>, List<KeyOffset>>() {
       @Override
       public List<KeyOffset> apply(@Nonnull List<SampleRowKeysResponse> rowKeysList) {
         if(rowKeysList == null || rowKeysList.isEmpty()){
@@ -180,7 +184,7 @@ public class BigtableDataClientWrapper implements IBigtableDataClient {
 
         return keyOffsetBuilder.build();
       }
-    }, MoreExecutors.directExecutor());
+    }, MoreExecutors.directExecutor()));
   }
 
   /** {@inheritDoc} */
@@ -218,10 +222,11 @@ public class BigtableDataClientWrapper implements IBigtableDataClient {
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<List<Row>> readRowsAsync(Query request) {
-    ListenableFuture<List<FlatRow>> responseProto = readFlatRowsAsync(request);
+  public ApiFuture<List<Row>> readRowsAsync(Query request) {
+    ApiFuture<List<FlatRow>> responseProto = readFlatRowsAsync(request);
 
-    return Futures.transform(responseProto, new Function<List<FlatRow>, List<Row>>() {
+    return ApiFutures.transform(responseProto,
+        new ApiFunction<List<FlatRow>, List<Row>>() {
       @Override
       public List<Row> apply(List<FlatRow> flatRowList) {
         ImmutableList.Builder<Row> rowBuilder =
@@ -249,8 +254,8 @@ public class BigtableDataClientWrapper implements IBigtableDataClient {
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<List<FlatRow>> readFlatRowsAsync(Query request) {
-    return delegate.readFlatRowsAsync(request.toProto(requestContext));
+  public ApiFuture<List<FlatRow>> readFlatRowsAsync(Query request) {
+    return ApiFutureUtil.adapt(delegate.readFlatRowsAsync(request.toProto(requestContext)));
   }
 
   /** {@inheritDoc} */
diff --git a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableTableAdminClientWrapper.java b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableTableAdminClientWrapper.java
index eab62d2cd..7bbe166c8 100644
--- a/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableTableAdminClientWrapper.java
+++ b/bigtable-client-core-parent/bigtable-client-core/src/main/java/com/google/cloud/bigtable/grpc/BigtableTableAdminClientWrapper.java
@@ -15,6 +15,7 @@
  */
 package com.google.cloud.bigtable.grpc;
 
+import com.google.api.core.ApiFuture;
 import com.google.bigtable.admin.v2.CreateTableFromSnapshotRequest;
 import com.google.bigtable.admin.v2.DeleteSnapshotRequest;
 import com.google.bigtable.admin.v2.DeleteTableRequest;
@@ -32,6 +33,7 @@ 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.core.IBigtableTableAdminClient;
+import com.google.cloud.bigtable.util.ApiFutureUtil;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
@@ -74,17 +76,17 @@ public class BigtableTableAdminClientWrapper implements IBigtableTableAdminClien
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<Table> createTableAsync(CreateTableRequest request) {
+  public ApiFuture<Table> createTableAsync(CreateTableRequest request) {
     com.google.bigtable.admin.v2.CreateTableRequest requestProto =
         request.toProto(instanceName.getProjectId(), instanceName.getInstanceId());
 
-    return Futures.transform(delegate.createTableAsync(requestProto),
+    return ApiFutureUtil.adapt(Futures.transform(delegate.createTableAsync(requestProto),
         new Function<com.google.bigtable.admin.v2.Table, Table>() {
           @Override
           public Table apply(com.google.bigtable.admin.v2.Table tableProto) {
             return Table.fromProto(tableProto);
           }
-        }, MoreExecutors.directExecutor());
+        }, MoreExecutors.directExecutor()));
   }
 
   /** {@inheritDoc} */
@@ -99,18 +101,18 @@ public class BigtableTableAdminClientWrapper implements IBigtableTableAdminClien
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<Table> getTableAsync(String tableId) {
+  public ApiFuture<Table> getTableAsync(String tableId) {
     GetTableRequest requestProto = GetTableRequest.newBuilder()
         .setName(instanceName.toTableNameStr(tableId))
         .build();
 
-    return Futures.transform(delegate.getTableAsync(requestProto),
+    return ApiFutureUtil.adapt(Futures.transform(delegate.getTableAsync(requestProto),
         new Function<com.google.bigtable.admin.v2.Table, Table>() {
           @Override
           public Table apply(com.google.bigtable.admin.v2.Table tableProto) {
             return Table.fromProto(tableProto);
           }
-        }, MoreExecutors.directExecutor());
+        }, MoreExecutors.directExecutor()));
   }
 
   /** {@inheritDoc} */
@@ -132,13 +134,14 @@ public class BigtableTableAdminClientWrapper implements IBigtableTableAdminClien
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<List<String>> listTablesAsync() {
+  public ApiFuture<List<String>> listTablesAsync() {
     ListTablesRequest request = ListTablesRequest.newBuilder()
         .setParent(instanceName.toString())
         .build();
     ListenableFuture<ListTablesResponse> response = delegate.listTablesAsync(request);
 
-    return Futures.transform(response, new Function<ListTablesResponse, List<String>>() {
+    return ApiFutureUtil.adapt(Futures.transform(response,
+        new Function<ListTablesResponse, List<String>>() {
       @Override
       public List<String> apply(ListTablesResponse input) {
         ImmutableList.Builder<String> tableIdsBuilder = ImmutableList.builder();
@@ -148,7 +151,7 @@ public class BigtableTableAdminClientWrapper implements IBigtableTableAdminClien
 
         return tableIdsBuilder.build();
       }
-    }, MoreExecutors.directExecutor());
+    }, MoreExecutors.directExecutor()));
   }
 
   /** {@inheritDoc} */
@@ -163,17 +166,18 @@ public class BigtableTableAdminClientWrapper implements IBigtableTableAdminClien
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<Void> deleteTableAsync(String tableId) {
+  public ApiFuture<Void> deleteTableAsync(String tableId) {
     DeleteTableRequest request = DeleteTableRequest.newBuilder()
         .setName(instanceName.toTableNameStr(tableId))
         .build();
 
-    return Futures.transform(delegate.deleteTableAsync(request), new Function<Empty, Void>() {
+    return ApiFutureUtil.adapt(Futures.transform(delegate.deleteTableAsync(request),
+        new Function<Empty, Void>() {
       @Override
       public Void apply(Empty empty) {
         return null;
       }
-    }, MoreExecutors.directExecutor());
+    }, MoreExecutors.directExecutor()));
   }
 
   /** {@inheritDoc} */
@@ -187,17 +191,17 @@ public class BigtableTableAdminClientWrapper implements IBigtableTableAdminClien
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<Table> modifyFamiliesAsync(ModifyColumnFamiliesRequest request) {
+  public ApiFuture<Table> modifyFamiliesAsync(ModifyColumnFamiliesRequest request) {
     com.google.bigtable.admin.v2.ModifyColumnFamiliesRequest modifyColumnRequestProto =
         request.toProto(instanceName.getProjectId(), instanceName.getInstanceId());
 
-    return Futures.transform(delegate.modifyColumnFamilyAsync(modifyColumnRequestProto),
+    return ApiFutureUtil.adapt(Futures.transform(delegate.modifyColumnFamilyAsync(modifyColumnRequestProto),
         new Function<com.google.bigtable.admin.v2.Table, Table>() {
       @Override
       public Table apply(com.google.bigtable.admin.v2.Table tableProto) {
         return Table.fromProto(tableProto);
       }
-    }, MoreExecutors.directExecutor());
+    }, MoreExecutors.directExecutor()));
   }
 
   /** {@inheritDoc} */
@@ -209,47 +213,47 @@ public class BigtableTableAdminClientWrapper implements IBigtableTableAdminClien
 
   /** {@inheritDoc} */
   @Override
-  public ListenableFuture<Void> dropRowRangeAsync(String tableId, String rowKeyPrefix) {
+  public ApiFuture<Void> dropRowRangeAsync(String tableId, String rowKeyPrefix) {
 
-    return Futures.transform(
+    return ApiFutureUtil.adapt(Futures.transform(
         delegate.dropRowRangeAsync(buildDropRowRangeRequest(tableId, rowKeyPrefix)),
         new Function<Empty, Void>() {
           @Override
           public Void apply(Empty empty) {
             return null;
           }
-        }, MoreExecutors.directExecutor());
+        }, MoreExecutors.directExecutor()));
   }
 
   @Override
-  public ListenableFuture<Operation> snapshotTableAsync(SnapshotTableRequest request) {
-    return delegate.snapshotTableAsync(request);
+  public ApiFuture<Operation> snapshotTableAsync(SnapshotTableRequest request) {
+    return ApiFutureUtil.adapt(delegate.snapshotTableAsync(request));
   }
 
   @Override
-  public ListenableFuture<Snapshot> getSnapshotAsync(GetSnapshotRequest request) {
-    return delegate.getSnapshotAsync(request);
+  public ApiFuture<Snapshot> getSnapshotAsync(GetSnapshotRequest request) {
+    return ApiFutureUtil.adapt(delegate.getSnapshotAsync(request));
   }
 
   @Override
-  public ListenableFuture<ListSnapshotsResponse> listSnapshotsAsync(ListSnapshotsRequest request) {
-    return delegate.listSnapshotsAsync(request);
+  public ApiFuture<ListSnapshotsResponse> listSnapshotsAsync(ListSnapshotsRequest request) {
+    return ApiFutureUtil.adapt(delegate.listSnapshotsAsync(request));
   }
 
   @Override
-  public ListenableFuture<Void> deleteSnapshotAsync(DeleteSnapshotRequest request) {
-    return Futures.transform(delegate.deleteSnapshotAsync(request), new Function<Empty, Void>() {
+  public ApiFuture<Void> deleteSnapshotAsync(DeleteSnapshotRequest request) {
+    return ApiFutureUtil.adapt(Futures.transform(delegate.deleteSnapshotAsync(request), new Function<Empty, Void>() {
       @Override
       public Void apply(Empty input) {
         return null;
       }
-    }, MoreExecutors.directExecutor());
+    }, MoreExecutors.directExecutor()));
   }
 
   @Override
-  public ListenableFuture<Operation> createTableFromSnapshotAsync(
+  public ApiFuture<Operation> createTableFromSnapshotAsync(
       CreateTableFromSnapshotRequest request) {
-    return delegate.createTableFromSnapshotAsync(request);
+    return ApiFutureUtil.adapt(delegate.createTableFromSnapshotAsync(request));
   }
 
   private DropRowRangeRequest buildDropRowRangeRequest(String tableId, String rowKeyPrefix) {
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 d53dcad2b..f55b2caf9 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
@@ -17,6 +17,10 @@
  */
 package com.google.cloud.bigtable.hbase;
 
+import com.google.api.core.ApiFunction;
+import com.google.api.core.ApiFuture;
+import com.google.api.core.ApiFutureCallback;
+import com.google.api.core.ApiFutures;
 import java.util.List;
 
 import javax.annotation.Nullable;
@@ -32,10 +36,7 @@ import com.google.cloud.bigtable.config.BigtableOptions;
 import com.google.cloud.bigtable.config.Logger;
 import com.google.cloud.bigtable.grpc.BigtableTableName;
 import com.google.cloud.bigtable.hbase.adapters.SampledRowKeysAdapter;
-import com.google.common.base.Function;
-import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
 
 /**
  * <p> AbstractBigtbleRegionLocator class. </p>
@@ -52,7 +53,7 @@ public abstract class AbstractBigtableRegionLocator {
   private static final Logger LOG = new Logger(AbstractBigtableRegionLocator.class);
 
   protected final TableName tableName;
-  private ListenableFuture<List<HRegionLocation>> regionsFuture;
+  private ApiFuture<List<HRegionLocation>> regionsFuture;
   private final IBigtableDataClient client;
   private final SampledRowKeysAdapter adapter;
   private final BigtableTableName bigtableTableName;
@@ -75,7 +76,7 @@ public abstract class AbstractBigtableRegionLocator {
    * @param reload a boolean field.
    * @return a {@link List} object.
    */
-  protected synchronized ListenableFuture<List<HRegionLocation>> getRegionsAsync(boolean reload) {
+  protected synchronized ApiFuture<List<HRegionLocation>> getRegionsAsync(boolean reload) {
     // If we don't need to refresh and we have a recent enough version, just use that.
     if (!reload && regionsFuture != null &&
         regionsFetchTimeMillis + MAX_REGION_AGE_MILLIS > System.currentTimeMillis()) {
@@ -85,16 +86,15 @@ public abstract class AbstractBigtableRegionLocator {
     LOG.debug("Sampling rowkeys for table %s", bigtableTableName.toString());
 
     try {
-      ListenableFuture<List<KeyOffset>> future =
+      ApiFuture<List<KeyOffset>> future =
           client.sampleRowKeysAsync(bigtableTableName.getTableId());
-      this.regionsFuture = Futures
-          .transform(future, new Function<List<KeyOffset>, List<HRegionLocation>>() {
+      this.regionsFuture = ApiFutures.transform(future, new ApiFunction<List<KeyOffset>, List<HRegionLocation>>() {
             @Override
             public List<HRegionLocation> apply(@Nullable List<KeyOffset> input) {
               return adapter.adaptResponse(input);
             }
           }, MoreExecutors.directExecutor());
-      Futures.addCallback(this.regionsFuture, new FutureCallback<List<HRegionLocation>>() {
+      ApiFutures.addCallback(this.regionsFuture, new ApiFutureCallback<List<HRegionLocation>>() {
         @Override public void onSuccess(@Nullable List<HRegionLocation> result) {
         }
         @Override public void onFailure(Throwable t) {
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 865493ea8..27aacb8f8 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
@@ -17,6 +17,9 @@ package org.apache.hadoop.hbase.client;
 
 import static com.google.cloud.bigtable.hbase.util.ModifyTableBuilder.buildModifications;
 
+import com.google.api.core.ApiFuture;
+import com.google.api.core.ApiFutureCallback;
+import com.google.api.core.ApiFutures;
 import com.google.bigtable.admin.v2.CreateTableFromSnapshotRequest;
 import com.google.bigtable.admin.v2.DeleteSnapshotRequest;
 import com.google.bigtable.admin.v2.SnapshotTableRequest;
@@ -32,7 +35,6 @@ import com.google.cloud.bigtable.hbase.BigtableOptionsFactory;
 import com.google.cloud.bigtable.hbase.adapters.admin.TableAdapter;
 import com.google.cloud.bigtable.hbase.util.ModifyTableBuilder;
 import com.google.common.base.MoreObjects;
-import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
@@ -351,10 +353,10 @@ public abstract class AbstractBigtableAdmin implements Admin {
    */
   protected ListenableFuture<Table> createTableAsync(final TableName tableName,
             CreateTableRequest request) throws IOException {
-    ListenableFuture<Table> future =
+    ApiFuture<Table> future =
         tableAdminClientWrapper.createTableAsync(request);
     final SettableFuture<Table> settableFuture = SettableFuture.create();
-    Futures.addCallback(future, new FutureCallback<Table>() {
+    ApiFutures.addCallback(future, new ApiFutureCallback<Table>() {
       @Override public void onSuccess(@Nullable Table result) {
         settableFuture.set(result);
       }
@@ -859,7 +861,7 @@ public abstract class AbstractBigtableAdmin implements Admin {
       );
     }
 
-    ListenableFuture<Operation> future = tableAdminClientWrapper
+    ApiFuture<Operation> future = tableAdminClientWrapper
         .snapshotTableAsync(requestBuilder.build());
 
     return Futures.getChecked(future, IOException.class);
diff --git a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAdmin.java b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAdmin.java
index 2ff1eeb92..79fb1a9ff 100644
--- a/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAdmin.java
+++ b/bigtable-hbase-2.x-parent/bigtable-hbase-2.x/src/main/java/com/google/cloud/bigtable/hbase2_x/BigtableAdmin.java
@@ -239,8 +239,7 @@ public class BigtableAdmin extends AbstractBigtableAdmin {
 
   protected CompletableFuture<Void> deleteTableAsyncInternal(TableName tableName) {
     return FutureUtils.toCompletableFuture(
-        tableAdminClientWrapper.deleteTableAsync(tableName.getNameAsString()))
-        .thenApply(r -> null);
+        tableAdminClientWrapper.deleteTableAsync(tableName.getNameAsString()));
   }
 
   @Override
@@ -347,8 +346,7 @@ public class BigtableAdmin extends AbstractBigtableAdmin {
    // rowKeyPrefix set to Empty String which truncates data from specified table.
    return FutureUtils.toCompletableFuture(
         tableAdminClientWrapper
-          .dropRowRangeAsync(tableName.getNameAsString(), ""))
-        .thenApply(r -> null);
+          .dropRowRangeAsync(tableName.getNameAsString(), ""));
   }
   /* ******* Unsupported methods *********** */
 
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 5feed3175..9d3af1377 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
@@ -231,8 +231,7 @@ public class BigtableAsyncTable implements AsyncTable<ScanResultConsumer> {
   @Override
   public CompletableFuture<Void> delete(Delete delete) {
     // figure out how to time this with Opencensus
-    return toCompletableFuture(clientWrapper.mutateRowAsync(hbaseAdapter.adapt(delete)))
-        .thenApply(r -> null);
+    return toCompletableFuture(clientWrapper.mutateRowAsync(hbaseAdapter.adapt(delete)));
   }
 
   /**
@@ -353,8 +352,7 @@ public class BigtableAsyncTable implements AsyncTable<ScanResultConsumer> {
    */
   @Override
   public CompletableFuture<Void> mutateRow(RowMutations rowMutations) {
-    return toCompletableFuture(clientWrapper.mutateRowAsync(hbaseAdapter.adapt(rowMutations)))
-        .thenApply(r -> null);
+    return toCompletableFuture(clientWrapper.mutateRowAsync(hbaseAdapter.adapt(rowMutations)));
   }
 
   /**
@@ -363,8 +361,7 @@ public class BigtableAsyncTable implements AsyncTable<ScanResultConsumer> {
   @Override
   public CompletableFuture<Void> put(Put put) {
     // figure out how to time this with Opencensus
-    return toCompletableFuture(clientWrapper.mutateRowAsync(hbaseAdapter.adapt(put)))
-        .thenApply(r -> null);
+    return toCompletableFuture(clientWrapper.mutateRowAsync(hbaseAdapter.adapt(put)));
   }
 
   /**


Test patch:
diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableDataClientWrapper.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableDataClientWrapper.java
index ccb042a31..6ab62111b 100644
--- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableDataClientWrapper.java
+++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableDataClientWrapper.java
@@ -155,7 +155,7 @@ public class TestBigtableDataClientWrapper {
     ListenableFuture<CheckAndMutateRowResponse> future = Futures.immediateFuture(response);
 
     when(client.checkAndMutateRowAsync(request)).thenReturn(future);
-    ListenableFuture<Boolean> actual = clientWrapper.checkAndMutateRowAsync(conditonalMutation);
+    ApiFuture<Boolean> actual = clientWrapper.checkAndMutateRowAsync(conditonalMutation);
     verify(client).checkAndMutateRowAsync(request);
     assertTrue(actual.get());
   }
@@ -172,7 +172,7 @@ public class TestBigtableDataClientWrapper {
     ListenableFuture<CheckAndMutateRowResponse> future = Futures.immediateFuture(response);
 
     when(client.checkAndMutateRowAsync(request)).thenReturn(future);
-    ListenableFuture<Boolean> actual = clientWrapper.checkAndMutateRowAsync(conditonalMutation);
+    ApiFuture<Boolean> actual = clientWrapper.checkAndMutateRowAsync(conditonalMutation);
     verify(client).checkAndMutateRowAsync(request);
     assertFalse(actual.get());
   }
diff --git a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableTableAdminClientWrapper.java b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableTableAdminClientWrapper.java
index bf8c04021..c206839c1 100644
--- a/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableTableAdminClientWrapper.java
+++ b/bigtable-client-core-parent/bigtable-client-core/src/test/java/com/google/cloud/bigtable/grpc/TestBigtableTableAdminClientWrapper.java
@@ -42,11 +42,11 @@ import com.google.cloud.bigtable.admin.v2.models.Table;
 import com.google.cloud.bigtable.config.BigtableOptions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
 import com.google.longrunning.Operation;
 import com.google.protobuf.ByteString;
 import com.google.protobuf.Empty;
 import java.util.List;
+import java.util.concurrent.Future;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -106,7 +106,7 @@ public class TestBigtableTableAdminClientWrapper {
 
     when(mockAdminClient.createTableAsync(request.toProto(PROJECT_ID, INSTANCE_ID)))
         .thenReturn(immediateFuture(createTableData()));
-    ListenableFuture<Table> response = clientWrapper.createTableAsync(request);
+    Future<Table> response = clientWrapper.createTableAsync(request);
 
     assertEquals(Table.fromProto(createTableData()), response.get());
     verify(mockAdminClient).createTableAsync(request.toProto(PROJECT_ID, INSTANCE_ID));
@@ -129,7 +129,7 @@ public class TestBigtableTableAdminClientWrapper {
 
     when(mockAdminClient.getTableAsync(request))
         .thenReturn(immediateFuture(createTableData()));
-    ListenableFuture<Table> response = clientWrapper.getTableAsync(TABLE_ID);
+    Future<Table> response = clientWrapper.getTableAsync(TABLE_ID);
 
     assertEquals(Table.fromProto(createTableData()), response.get());
     verify(mockAdminClient).getTableAsync(request);
@@ -165,7 +165,7 @@ public class TestBigtableTableAdminClientWrapper {
     builder.addTablesBuilder().setName(INSTANCE_NAME.toTableNameStr(TEST_TABLE_ID_3)).build();
 
     when(mockAdminClient.listTablesAsync(request)).thenReturn(immediateFuture(builder.build()));
-    ListenableFuture<List<String>> actualResponse = clientWrapper.listTablesAsync();
+    Future<List<String>> actualResponse = clientWrapper.listTablesAsync();
 
     assertEquals(tableIdList, actualResponse.get());
     verify(mockAdminClient).listTablesAsync(request);
@@ -218,7 +218,7 @@ public class TestBigtableTableAdminClientWrapper {
 
     when(mockAdminClient.modifyColumnFamilyAsync(request.toProto(PROJECT_ID, INSTANCE_ID)))
         .thenReturn(immediateFuture(createTableData()));
-    ListenableFuture<Table> response = clientWrapper.modifyFamiliesAsync(request);
+    Future<Table> response = clientWrapper.modifyFamiliesAsync(request);
 
     assertEquals(Table.fromProto(createTableData()), response.get());
     verify(mockAdminClient).modifyColumnFamilyAsync(request.toProto(PROJECT_ID, INSTANCE_ID));
@@ -288,7 +288,7 @@ public class TestBigtableTableAdminClientWrapper {
         .build();
     Operation response = Operation.getDefaultInstance();
     when(mockAdminClient.snapshotTableAsync(request)).thenReturn(Futures.immediateFuture(response));
-    ListenableFuture<Operation> actualResponse = clientWrapper.snapshotTableAsync(request);
+    Future<Operation> actualResponse = clientWrapper.snapshotTableAsync(request);
     assertEquals(response, actualResponse.get());
     verify(mockAdminClient).snapshotTableAsync(request);
   }
@@ -300,7 +300,7 @@ public class TestBigtableTableAdminClientWrapper {
         .build();
     Snapshot response = Snapshot.getDefaultInstance();
     when(mockAdminClient.getSnapshotAsync(request)).thenReturn(Futures.immediateFuture(response));
-    ListenableFuture<Snapshot> actualResponse = clientWrapper.getSnapshotAsync(request);
+    Future<Snapshot> actualResponse = clientWrapper.getSnapshotAsync(request);
     assertEquals(response, actualResponse.get());
     verify(mockAdminClient).getSnapshotAsync(request);
   }
@@ -312,7 +312,7 @@ public class TestBigtableTableAdminClientWrapper {
         .build();
     ListSnapshotsResponse response = ListSnapshotsResponse.getDefaultInstance();
     when(mockAdminClient.listSnapshotsAsync(request)).thenReturn(Futures.immediateFuture(response));
-    ListenableFuture<ListSnapshotsResponse> actualResponse = clientWrapper.listSnapshotsAsync(request);
+    Future<ListSnapshotsResponse> actualResponse = clientWrapper.listSnapshotsAsync(request);
     assertEquals(response, actualResponse.get());
     verify(mockAdminClient).listSnapshotsAsync(request);
   }
@@ -338,7 +338,7 @@ public class TestBigtableTableAdminClientWrapper {
     Operation response = Operation.getDefaultInstance();
     when(mockAdminClient.createTableFromSnapshotAsync(request))
         .thenReturn(Futures.immediateFuture(response));
-    ListenableFuture<Operation> actualResponse = clientWrapper.createTableFromSnapshotAsync(request);
+    Future<Operation> actualResponse = clientWrapper.createTableFromSnapshotAsync(request);
     assertEquals(response, actualResponse.get());
     verify(mockAdminClient).createTableFromSnapshotAsync(request);
   }