Skip to content

Commit

Permalink
Amazon Services - Fix class loading issues by separating recorders
Browse files Browse the repository at this point in the history
Fixes quarkusio#15014

(cherry picked from commit 04bab61)
  • Loading branch information
gsmet committed Feb 16, 2021
1 parent 78255eb commit 719d83c
Show file tree
Hide file tree
Showing 18 changed files with 782 additions and 429 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import org.jboss.jandex.DotName;
import org.jboss.jandex.Type;

import io.quarkus.amazon.common.runtime.AmazonClientApacheTransportRecorder;
import io.quarkus.amazon.common.runtime.AmazonClientNettyTransportRecorder;
import io.quarkus.amazon.common.runtime.AmazonClientRecorder;
import io.quarkus.amazon.common.runtime.AmazonClientTransportRecorder;
import io.quarkus.amazon.common.runtime.AmazonClientUrlConnectionTransportRecorder;
import io.quarkus.amazon.common.runtime.AwsConfig;
import io.quarkus.amazon.common.runtime.NettyHttpClientConfig;
import io.quarkus.amazon.common.runtime.SdkBuildTimeConfig;
Expand Down Expand Up @@ -72,61 +74,103 @@ protected void setupExtension(BeanRegistrationPhaseBuildItem beanRegistrationPha
}
}

public void createTransportBuilders(List<AmazonClientBuildItem> amazonClients,
AmazonClientTransportRecorder recorder,
protected void createApacheSyncTransportBuilder(List<AmazonClientBuildItem> amazonClients,
AmazonClientApacheTransportRecorder recorder,
SyncHttpClientBuildTimeConfig buildSyncConfig,
RuntimeValue<SyncHttpClientConfig> syncConfig,
RuntimeValue<NettyHttpClientConfig> asyncConfig,
BuildProducer<AmazonClientTransportsBuildItem> clientTransports) {
BuildProducer<AmazonClientSyncTransportBuildItem> clientSyncTransports) {

Optional<AmazonClientBuildItem> matchingClientBuildItem = amazonClients.stream()
.filter(c -> c.getAwsClientName().equals(configName()))
.findAny();

matchingClientBuildItem.ifPresent(client -> {
RuntimeValue<SdkHttpClient.Builder> syncTransport = null;
RuntimeValue<SdkAsyncHttpClient.Builder> asyncTransport = null;

if (client.getSyncClassName().isPresent()) {
if (buildSyncConfig.type == SyncHttpClientBuildTimeConfig.SyncClientType.APACHE) {
syncTransport = recorder.configureSyncApacheHttpClient(configName(), syncConfig);
} else {
syncTransport = recorder.configureSyncUrlConnectionHttpClient(configName(), syncConfig);
}
if (!client.getSyncClassName().isPresent()) {
return;
}
if (buildSyncConfig.type != SyncHttpClientBuildTimeConfig.SyncClientType.APACHE) {
return;
}

clientSyncTransports.produce(
new AmazonClientSyncTransportBuildItem(
client.getAwsClientName(),
client.getSyncClassName().get(),
recorder.configureSync(configName(), syncConfig)));
});
}

protected void createUrlConnectionSyncTransportBuilder(List<AmazonClientBuildItem> amazonClients,
AmazonClientUrlConnectionTransportRecorder recorder,
SyncHttpClientBuildTimeConfig buildSyncConfig,
RuntimeValue<SyncHttpClientConfig> syncConfig,
BuildProducer<AmazonClientSyncTransportBuildItem> clientSyncTransports) {

Optional<AmazonClientBuildItem> matchingClientBuildItem = amazonClients.stream()
.filter(c -> c.getAwsClientName().equals(configName()))
.findAny();

if (client.getAsyncClassName().isPresent()) {
asyncTransport = recorder.configureAsync(configName(), asyncConfig);
matchingClientBuildItem.ifPresent(client -> {
if (!client.getSyncClassName().isPresent()) {
return;
}
if (buildSyncConfig.type != SyncHttpClientBuildTimeConfig.SyncClientType.URL) {
return;
}

clientTransports.produce(
new AmazonClientTransportsBuildItem(
client.getSyncClassName(), client.getAsyncClassName(),
syncTransport,
asyncTransport,
client.getAwsClientName()));
clientSyncTransports.produce(
new AmazonClientSyncTransportBuildItem(
client.getAwsClientName(),
client.getSyncClassName().get(),
recorder.configureSync(configName(), syncConfig)));
});
}

protected void createNettyAsyncTransportBuilder(List<AmazonClientBuildItem> amazonClients,
AmazonClientNettyTransportRecorder recorder,
RuntimeValue<NettyHttpClientConfig> asyncConfig,
BuildProducer<AmazonClientAsyncTransportBuildItem> clientAsyncTransports) {

Optional<AmazonClientBuildItem> matchingClientBuildItem = amazonClients.stream()
.filter(c -> c.getAwsClientName().equals(configName()))
.findAny();

matchingClientBuildItem.ifPresent(client -> {
if (!client.getAsyncClassName().isPresent()) {
return;
}

clientAsyncTransports.produce(
new AmazonClientAsyncTransportBuildItem(
client.getAwsClientName(),
client.getAsyncClassName().get(),
recorder.configureAsync(configName(), asyncConfig)));
});
}

protected void createClientBuilders(List<AmazonClientTransportsBuildItem> clients,
protected void createClientBuilders(List<AmazonClientSyncTransportBuildItem> syncClientBuilders,
List<AmazonClientAsyncTransportBuildItem> asyncClientBuilders,
BuildProducer<AmazonClientBuilderBuildItem> builderProducer,
Function<RuntimeValue<SdkHttpClient.Builder>, RuntimeValue<AwsClientBuilder>> syncFunc,
Function<RuntimeValue<SdkAsyncHttpClient.Builder>, RuntimeValue<AwsClientBuilder>> asyncFunc) {

for (AmazonClientTransportsBuildItem client : clients) {
if (configName().equals(client.getAwsClientName())) {
RuntimeValue<AwsClientBuilder> syncBuilder = null;
RuntimeValue<AwsClientBuilder> asyncBuilder = null;
if (client.getSyncClassName().isPresent()) {
syncBuilder = syncFunc.apply(client.getSyncTransport());
}
if (client.getAsyncClassName().isPresent()) {
asyncBuilder = asyncFunc.apply(client.getAsyncTransport());
}
builderProducer.produce(new AmazonClientBuilderBuildItem(client.getAwsClientName(), syncBuilder, asyncBuilder));
}
String configName = configName();

Optional<RuntimeValue<SdkHttpClient.Builder>> syncClientBuilder = syncClientBuilders.stream()
.filter(c -> configName.equals(c.getAwsClientName()))
.map(c -> c.getClientBuilder())
.findFirst();
Optional<RuntimeValue<SdkAsyncHttpClient.Builder>> asyncClientBuilder = asyncClientBuilders.stream()
.filter(c -> configName.equals(c.getAwsClientName()))
.map(c -> c.getClientBuilder())
.findFirst();

if (!syncClientBuilder.isPresent() && !asyncClientBuilder.isPresent()) {
return;
}

builderProducer.produce(new AmazonClientBuilderBuildItem(configName,
syncClientBuilder.isPresent() ? syncFunc.apply(syncClientBuilder.get()) : null,
asyncClientBuilder.isPresent() ? asyncFunc.apply(asyncClientBuilder.get()) : null));
}

protected void buildClients(List<AmazonClientBuilderConfiguredBuildItem> configuredClients,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.quarkus.amazon.common.deployment;

import org.jboss.jandex.DotName;

import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.runtime.RuntimeValue;
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;

public final class AmazonClientAsyncTransportBuildItem extends MultiBuildItem {

private final String awsClientName;
private final DotName className;
private final RuntimeValue<SdkAsyncHttpClient.Builder> clientBuilder;

public AmazonClientAsyncTransportBuildItem(String awsClientName,
DotName className,
RuntimeValue<SdkAsyncHttpClient.Builder> clientBuilder) {
this.awsClientName = awsClientName;
this.className = className;
this.clientBuilder = clientBuilder;
}

public String getAwsClientName() {
return awsClientName;
}

public DotName getClassName() {
return className;
}

public RuntimeValue<SdkAsyncHttpClient.Builder> getClientBuilder() {
return clientBuilder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.quarkus.amazon.common.deployment;

import org.jboss.jandex.DotName;

import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.runtime.RuntimeValue;
import software.amazon.awssdk.http.SdkHttpClient;

public final class AmazonClientSyncTransportBuildItem extends MultiBuildItem {

private final String awsClientName;
private final DotName className;
private final RuntimeValue<SdkHttpClient.Builder> clientBuilder;

public AmazonClientSyncTransportBuildItem(String awsClientName,
DotName className,
RuntimeValue<SdkHttpClient.Builder> clientBuilder) {
this.awsClientName = awsClientName;
this.className = className;
this.clientBuilder = clientBuilder;
}

public String getAwsClientName() {
return awsClientName;
}

public DotName getClassName() {
return className;
}

public RuntimeValue<SdkHttpClient.Builder> getClientBuilder() {
return clientBuilder;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.quarkus.amazon.common.deployment;

import java.util.function.BooleanSupplier;

public class AmazonHttpClients {

public static final String APACHE_HTTP_SERVICE = "software.amazon.awssdk.http.apache.ApacheSdkHttpService";
public static final String NETTY_HTTP_SERVICE = "software.amazon.awssdk.http.nio.netty.NettySdkAsyncHttpService";
public static final String URL_CONNECTION_HTTP_SERVICE = "software.amazon.awssdk.http.urlconnection.UrlConnectionSdkHttpService";

public static class IsAmazonApacheHttpServicePresent implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
try {
Class.forName(APACHE_HTTP_SERVICE);
return true;
} catch (Exception e) {
return false;
}
}
};

public static class IsAmazonNettyHttpServicePresent implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
try {
Class.forName(NETTY_HTTP_SERVICE);
return true;
} catch (Exception e) {
return false;
}
}
};

public static class IsAmazonUrlConnectionHttpServicePresent implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
try {
Class.forName(URL_CONNECTION_HTTP_SERVICE);
return true;
} catch (Exception e) {
return false;
}
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ public class AmazonServicesClientsProcessor {
public static final String AWS_SDK_APPLICATION_ARCHIVE_MARKERS = "software/amazon/awssdk";
public static final String AWS_SDK_XRAY_ARCHIVE_MARKER = "com/amazonaws/xray";

private static final String APACHE_HTTP_SERVICE = "software.amazon.awssdk.http.apache.ApacheSdkHttpService";
private static final String NETTY_HTTP_SERVICE = "software.amazon.awssdk.http.nio.netty.NettySdkAsyncHttpService";
private static final String URL_HTTP_SERVICE = "software.amazon.awssdk.http.urlconnection.UrlConnectionSdkHttpService";

private static final DotName EXECUTION_INTERCEPTOR_NAME = DotName.createSimple(ExecutionInterceptor.class.getName());

@BuildStep
Expand Down Expand Up @@ -98,9 +94,9 @@ void setup(CombinedIndexBuildItem combinedIndexBuildItem,
// Register what's needed depending on the clients in the classpath and the configuration.
// We use the configuration to guide us but if we don't have any clients configured,
// we still register what's needed depending on what is in the classpath.
boolean isSyncApacheInClasspath = isInClasspath(APACHE_HTTP_SERVICE);
boolean isSyncUrlConnectionInClasspath = isInClasspath(URL_HTTP_SERVICE);
boolean isAsyncInClasspath = isInClasspath(NETTY_HTTP_SERVICE);
boolean isSyncApacheInClasspath = isInClasspath(AmazonHttpClients.APACHE_HTTP_SERVICE);
boolean isSyncUrlConnectionInClasspath = isInClasspath(AmazonHttpClients.URL_CONNECTION_HTTP_SERVICE);
boolean isAsyncInClasspath = isInClasspath(AmazonHttpClients.NETTY_HTTP_SERVICE);

// Check that the clients required by the configuration are available
if (syncTransportNeeded) {
Expand Down Expand Up @@ -140,17 +136,18 @@ private static void registerSyncApacheClient(BuildProducer<NativeImageProxyDefin
"software.amazon.awssdk.http.apache.internal.conn.Wrapped"));

serviceProvider.produce(
new ServiceProviderBuildItem(SdkHttpService.class.getName(), APACHE_HTTP_SERVICE));
new ServiceProviderBuildItem(SdkHttpService.class.getName(), AmazonHttpClients.APACHE_HTTP_SERVICE));
}

private static void registerSyncUrlConnectionClient(BuildProducer<ServiceProviderBuildItem> serviceProvider) {
serviceProvider.produce(new ServiceProviderBuildItem(SdkHttpService.class.getName(), URL_HTTP_SERVICE));
serviceProvider.produce(
new ServiceProviderBuildItem(SdkHttpService.class.getName(), AmazonHttpClients.URL_CONNECTION_HTTP_SERVICE));
}

private static void registerAsyncNettyClient(BuildProducer<ServiceProviderBuildItem> serviceProvider) {
serviceProvider.produce(
new ServiceProviderBuildItem(SdkAsyncHttpService.class.getName(),
NETTY_HTTP_SERVICE));
AmazonHttpClients.NETTY_HTTP_SERVICE));
}

private static boolean isInClasspath(String className) {
Expand Down
Loading

0 comments on commit 719d83c

Please sign in to comment.