Skip to content

Commit

Permalink
feat: use concrete classes for hbase.client.registry.impl (#4043) (#4188
Browse files Browse the repository at this point in the history
)

Previously we used runtime bytecode generation which prevented endusers from using hbase-site.xml to target bigtable in hbase 2 applications. This PR will create a concrete implementation for both AsyncRegistry for (hbase < 2.3) and ConnectionRegistry (for hbase >= 2.3). 
To accomplish this, we use a local copy of the AsyncRegistry interface from HBase 2.2 that we use as a compile time target and then strip it from the resulting jar.

After this change end users should be able to use async apis in hbase 2 using hbase-site.xml. Examples:



```xml
<configuration>
    <property>
        <name>hbase.client.connection.impl</name>
        <value>com.google.cloud.bigtable.hbase2_x.BigtableConnection</value>
    </property>
    <property>
        <name>hbase.client.async.connection.impl</name>
        <value>org.apache.hadoop.hbase.client.BigtableAsyncConnection</value>
    </property>
    <property>
        <name>hbase.client.registry.impl</name>
        <!-- When using hbase >= 2.3, use this -->
        <value>org.apache.hadoop.hbase.client.BigtableConnectionRegistry</value>
        <!-- When using hbase < 2.3, use this -->
        <!-- <value>org.apache.hadoop.hbase.client.BigtableAsyncRegistry</value> -->
    </property>
    <property>
        <name>google.bigtable.project.id</name>
        <value>my-project</value>
    </property>
    <property>
        <name>google.bigtable.instance.id</name>
        <value>my-instance</value>
    </property>
    <property>
        <name>google.bigtable.app_profile.id</name>
        <value>my-app-profile</value>
    </property>
</configuration>
```

```java
AsyncConnection asyncConnection = ConnectionFactory.createAsyncConnection().get();
```
  • Loading branch information
igorbernstein2 committed Oct 18, 2023
1 parent ab4c790 commit cc22f2f
Show file tree
Hide file tree
Showing 12 changed files with 930 additions and 167 deletions.
6 changes: 0 additions & 6 deletions bigtable-client-core-parent/bigtable-hbase/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,6 @@ limitations under the License.
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${byte.buddy.version}</version>
</dependency>

<!-- Test -->
<dependency>
<groupId>com.google.cloud.bigtable</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.google.auth.Credentials;
import com.google.common.base.Preconditions;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.BigtableAsyncRegistry;
import org.apache.hadoop.hbase.client.Connection;

/** This class provides a simplified mechanism of creating a programmatic Bigtable Connection. */
Expand All @@ -35,34 +34,20 @@ public class BigtableConfiguration {
public static final String HBASE_CLIENT_ASYNC_CONNECTION_IMPL =
"hbase.client.async.connection.impl";

// The value of this field can implement 2 different interfaces depending on the HBase version
// For 2.0 - 2.2 the value must implement AsyncRegistry
// For 2.3 onwards the value must implement ConnectionRegistry
// bigable-hbase-2x contains implementations for both, this helper will use classpath probing to
// guess the correct impl.
/** For internal use only - public for technical reasons. */
@InternalApi("For internal usage only")
public static final String HBASE_CLIENT_ASYNC_REGISTRY_IMPL = "hbase.client.registry.impl";

/** For internal use only - public for technical reasons. */
@InternalApi("For internal usage only")
public static final String BIGTABLE_HBASE_CLIENT_ASYNC_CONNECTION_CLASS =
"org.apache.hadoop.hbase.client.BigtableAsyncConnection";

/** For internal use only - public for technical reasons. */
@InternalApi("For internal usage only")
public static final String BIGTABLE_HBASE_CLIENT_ASYNC_REGISTRY_CLASS =
"org.apache.hadoop.hbase.client.BigtableAsyncRegistry";

private static final String HBASE_ASYNC_CONNECTION_CLASS =
"org.apache.hadoop.hbase.client.AsyncConnection";

private static final String[] CONNECTION_CLASS_NAMES = {
"com.google.cloud.bigtable.hbase1_x.BigtableConnection",
"com.google.cloud.bigtable.hbase2_x.BigtableConnection",
};

private static final String[] ASYNC_CONNECTION_CLASS_NAMES = {
BIGTABLE_HBASE_CLIENT_ASYNC_CONNECTION_CLASS,
BIGTABLE_HBASE_CLIENT_ASYNC_REGISTRY_CLASS,
HBASE_ASYNC_CONNECTION_CLASS
};

private static final Class<? extends Connection> CONNECTION_CLASS = chooseConnectionClass();

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -91,24 +76,57 @@ public static Class<? extends Connection> getConnectionClass() {
return CONNECTION_CLASS;
}

private static Class<?> getConnectionRegistryClass() {
try {
Class.forName("org.apache.hadoop.hbase.client.ConnectionRegistry");
return Class.forName("org.apache.hadoop.hbase.client.BigtableConnectionRegistry");
} catch (ClassNotFoundException e) {
// noop
}

try {
Class.forName("org.apache.hadoop.hbase.client.AsyncRegistry");
return Class.forName("org.apache.hadoop.hbase.client.BigtableAsyncRegistry");
} catch (ClassNotFoundException e) {
// noop
}

return null;
}

private static Class<?> getAsyncConnectionClass() {
try {
// Make sure HBase interface is present
Class.forName("org.apache.hadoop.hbase.client.AsyncConnection");
} catch (ClassNotFoundException e) {
return null;
}

try {
// then try loading our implementation
return Class.forName("org.apache.hadoop.hbase.client.BigtableAsyncConnection");
} catch (ClassNotFoundException e) {
return null;
}
}

/**
* Set up connection impl classes. If Bigtable and HBase async connection classes exist, set up
* async connection impl class as well.
*/
private static Configuration injectBigtableImpls(Configuration configuration) {
// HBase 1x & 2x sync connection
configuration.set(HBASE_CLIENT_CONNECTION_IMPL, getConnectionClass().getCanonicalName());
try {
// Set up HBase async registry impl if async connection classes exist
for (String className : ASYNC_CONNECTION_CLASS_NAMES) {
Class.forName(className);
}
configuration.set(
HBASE_CLIENT_ASYNC_CONNECTION_IMPL, BIGTABLE_HBASE_CLIENT_ASYNC_CONNECTION_CLASS);
configuration.set(
HBASE_CLIENT_ASYNC_REGISTRY_IMPL, BigtableAsyncRegistry.getSubClass().getName());
} catch (ClassNotFoundException ignored) {
// Skip if any of the async connection class doesn't exist

// HBase 2x async
Class<?> asyncConnectionClass = getAsyncConnectionClass();
Class<?> connectionRegistryClass = getConnectionRegistryClass();

if (asyncConnectionClass != null && connectionRegistryClass != null) {
configuration.set(HBASE_CLIENT_ASYNC_CONNECTION_IMPL, asyncConnectionClass.getName());
configuration.set(HBASE_CLIENT_ASYNC_REGISTRY_IMPL, connectionRegistryClass.getName());
}

return configuration;
}

Expand Down Expand Up @@ -179,25 +197,6 @@ public static Configuration withCredentials(Configuration conf, Credentials cred
return new BigtableExtendedConfiguration(conf, credentials);
}

/**
* Configuration for getting a org.apache.hadoop.hbase.client.AsyncConnection.
*
* @param conf a {@link org.apache.hadoop.conf.Configuration} object to configure.
* @return the modified {@link org.apache.hadoop.conf.Configuration} object.
* @deprecated For HBase 2.x async connections, please use {@link #configure(String, String)}
* directly.
* <pre>{@code
* Configure config = BigtableConfiguration.configure(projectId, instanceId);
* AsyncConnection asyncConnection = ConnectionFactory.createAsyncConnection(config).get();
* }</pre>
*/
@Deprecated
public static Configuration asyncConfigure(Configuration conf) {
conf.set(HBASE_CLIENT_ASYNC_CONNECTION_IMPL, BIGTABLE_HBASE_CLIENT_ASYNC_CONNECTION_CLASS);
conf.set(HBASE_CLIENT_ASYNC_REGISTRY_IMPL, BigtableAsyncRegistry.getSubClass().getName());
return conf;
}

/**
* connect.
*
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ limitations under the License.
<classEntry>org/apache/hadoop/hbase/client/AbstractBigtableAdmin</classEntry>
<classEntry>org/apache/hadoop/hbase/client/AbstractBigtableConnection</classEntry>
<classEntry>org/apache/hadoop/hbase/client/BigtableAsyncConnection</classEntry>
<classEntry>org/apache/hadoop/hbase/client/BigtableConnectionRegistry</classEntry>
<classEntry>org/apache/hadoop/hbase/client/BigtableAsyncRegistry</classEntry>
<classEntry>org/apache/hadoop/hbase/client/CommonConnection</classEntry>
</allowedJarClassEntries>
Expand Down
2 changes: 2 additions & 0 deletions bigtable-hbase-2.x-parent/bigtable-hbase-2.x-shaded/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,10 @@ limitations under the License.
<classEntry>org/apache/hadoop/hbase/client/AbstractBigtableAdmin</classEntry>
<classEntry>org/apache/hadoop/hbase/client/AbstractBigtableConnection</classEntry>
<classEntry>org/apache/hadoop/hbase/client/BigtableAsyncConnection</classEntry>
<classEntry>org/apache/hadoop/hbase/client/BigtableConnectionRegistry</classEntry>
<classEntry>org/apache/hadoop/hbase/client/BigtableAsyncRegistry</classEntry>
<classEntry>org/apache/hadoop/hbase/client/CommonConnection</classEntry>
<classEntry>org/apache/hadoop/hbase/client/BigtableConnectionRegistry</classEntry>
</allowedJarClassEntries>
</configuration>
</execution>
Expand Down
38 changes: 38 additions & 0 deletions bigtable-hbase-2.x-parent/bigtable-hbase-2.x/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,22 @@ limitations under the License.
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<!-- AsyncRegistry was an interface that existed in hbase 2.0-2.2. It's no longer shipped. To ensure
compatibility we vendored it in this project to compile against, but do not want to ship it our binary -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<exclude>org/apache/hadoop/hbase/client/AsyncRegistry.class</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</pluginManagement>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand All @@ -205,6 +221,9 @@ limitations under the License.
See bigtable-hbase-1.x pom.xml for more details-->
<ignoredNonTestScopedDependency>*</ignoredNonTestScopedDependency>
</ignoredNonTestScopedDependencies>
<ignoredDependencies>
<dependency>*</dependency>
</ignoredDependencies>
</configuration>
</plugin>
<plugin>
Expand All @@ -215,6 +234,25 @@ limitations under the License.
<skip>true</skip>
</configuration>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>../../third_party/third_party_hbase_client_pre23/src/main/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

0 comments on commit cc22f2f

Please sign in to comment.