Skip to content

Commit

Permalink
Properly initialize reactive Pool beans
Browse files Browse the repository at this point in the history
We introduce an injection point to the
synthetic bean creation process thus
giving Arc all the declarative context
it needs in order to ensure proper bean
creation order
  • Loading branch information
geoand committed Sep 15, 2023
1 parent 8625c06 commit dc050e5
Show file tree
Hide file tree
Showing 16 changed files with 353 additions and 163 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,23 @@
*/
public final class VertxPoolBuildItem extends MultiBuildItem {

private final RuntimeValue<? extends Pool> vertxPool;
private final String dbKind;
private final boolean isDefault;
public VertxPoolBuildItem() {
}

public VertxPoolBuildItem(RuntimeValue<? extends Pool> vertxPool, String dbKind, boolean isDefault) {
this.vertxPool = vertxPool;
this.dbKind = dbKind;
this.isDefault = isDefault;

}

public RuntimeValue<? extends Pool> getPool() {
return vertxPool;
throw new IllegalStateException("should never be called");
}

public String getDbKind() {
return dbKind;
throw new IllegalStateException("should never be called");
}

public boolean isDefault() {
return isDefault;
throw new IllegalStateException("should never be called");
}

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package io.quarkus.reactive.db2.client.deployment;

import java.util.function.Function;

import io.quarkus.arc.SyntheticCreationalContext;
import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.datasource.common.runtime.DataSourceUtil;
import io.quarkus.runtime.RuntimeValue;
import io.vertx.db2client.DB2Pool;

public final class DB2PoolBuildItem extends MultiBuildItem {

private final String dataSourceName;

private final RuntimeValue<DB2Pool> db2Pool;
private final Function<SyntheticCreationalContext<DB2Pool>, DB2Pool> db2Pool;

public DB2PoolBuildItem(String dataSourceName, RuntimeValue<DB2Pool> db2Pool) {
public DB2PoolBuildItem(String dataSourceName, Function<SyntheticCreationalContext<DB2Pool>, DB2Pool> db2Pool) {
this.dataSourceName = dataSourceName;
this.db2Pool = db2Pool;
}
Expand All @@ -20,7 +22,7 @@ public String getDataSourceName() {
return dataSourceName;
}

public RuntimeValue<DB2Pool> getDB2Pool() {
public Function<SyntheticCreationalContext<DB2Pool>, DB2Pool> getDB2Pool() {
return db2Pool;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Instance;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassType;
import org.jboss.jandex.DotName;
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;

import io.quarkus.arc.SyntheticCreationalContext;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem.ExtendedBeanConfigurator;
import io.quarkus.arc.deployment.UnremovableBeanBuildItem;
Expand Down Expand Up @@ -51,7 +56,6 @@
import io.quarkus.reactive.db2.client.runtime.DB2PoolRecorder;
import io.quarkus.reactive.db2.client.runtime.DB2ServiceBindingConverter;
import io.quarkus.reactive.db2.client.runtime.DataSourcesReactiveDB2Config;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem;
import io.quarkus.vertx.core.deployment.EventLoopCountBuildItem;
import io.quarkus.vertx.deployment.VertxBuildItem;
Expand All @@ -60,6 +64,12 @@

class ReactiveDB2ClientProcessor {

private static final ParameterizedType POOL_INJECTION_TYPE = ParameterizedType.create(DotName.createSimple(Instance.class),
new Type[] { ClassType.create(DotName.createSimple(DB2PoolCreator.class.getName())) }, null);
private static final AnnotationInstance[] EMPTY_ANNOTATIONS = new AnnotationInstance[0];

private static final DotName REACTIVE_DATASOURCE = DotName.createSimple(ReactiveDataSource.class);

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
ServiceStartBuildItem build(BuildProducer<FeatureBuildItem> feature,
Expand All @@ -81,7 +91,7 @@ ServiceStartBuildItem build(BuildProducer<FeatureBuildItem> feature,
feature.produce(new FeatureBuildItem(Feature.REACTIVE_DB2_CLIENT));

for (String dataSourceName : dataSourcesBuildTimeConfig.dataSources().keySet()) {
createPoolIfDefined(recorder, vertx, eventLoopCount, shutdown, db2Pool, vertxPool, syntheticBeans, dataSourceName,
createPoolIfDefined(recorder, vertx, eventLoopCount, shutdown, db2Pool, syntheticBeans, dataSourceName,
dataSourcesBuildTimeConfig, dataSourcesRuntimeConfig, dataSourcesReactiveBuildTimeConfig,
dataSourcesReactiveRuntimeConfig, dataSourcesReactiveDB2Config, defaultDataSourceDbKindBuildItems,
curateOutcomeBuildItem);
Expand All @@ -90,6 +100,7 @@ ServiceStartBuildItem build(BuildProducer<FeatureBuildItem> feature,
// Enable SSL support by default
sslNativeSupport.produce(new ExtensionSslNativeSupportBuildItem(Feature.REACTIVE_DB2_CLIENT));

vertxPool.produce(new VertxPoolBuildItem());
return new ServiceStartBuildItem("reactive-db2-client");
}

Expand Down Expand Up @@ -168,7 +179,6 @@ private void createPoolIfDefined(DB2PoolRecorder recorder,
EventLoopCountBuildItem eventLoopCount,
ShutdownContextBuildItem shutdown,
BuildProducer<DB2PoolBuildItem> db2Pool,
BuildProducer<VertxPoolBuildItem> vertxPool,
BuildProducer<SyntheticBeanBuildItem> syntheticBeans,
String dataSourceName,
DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig,
Expand All @@ -184,20 +194,21 @@ private void createPoolIfDefined(DB2PoolRecorder recorder,
return;
}

RuntimeValue<DB2Pool> pool = recorder.configureDB2Pool(vertx.getVertx(),
Function<SyntheticCreationalContext<DB2Pool>, DB2Pool> poolFunction = recorder.configureDB2Pool(vertx.getVertx(),
eventLoopCount.getEventLoopCount(),
dataSourceName,
dataSourcesRuntimeConfig,
dataSourcesReactiveRuntimeConfig,
dataSourcesReactiveDB2Config,
shutdown);
db2Pool.produce(new DB2PoolBuildItem(dataSourceName, pool));
db2Pool.produce(new DB2PoolBuildItem(dataSourceName, poolFunction));

ExtendedBeanConfigurator db2PoolBeanConfigurator = SyntheticBeanBuildItem.configure(DB2Pool.class)
.defaultBean()
.addType(Pool.class)
.scope(ApplicationScoped.class)
.runtimeValue(pool)
.addInjectionPoint(POOL_INJECTION_TYPE, injectionPointAnnotations(dataSourceName))
.createWith(poolFunction)
.unremovable()
.setRuntimeInit();

Expand All @@ -209,14 +220,21 @@ private void createPoolIfDefined(DB2PoolRecorder recorder,
.configure(io.vertx.mutiny.db2client.DB2Pool.class)
.defaultBean()
.scope(ApplicationScoped.class)
.runtimeValue(recorder.mutinyDB2Pool(pool))
.addInjectionPoint(POOL_INJECTION_TYPE, injectionPointAnnotations(dataSourceName))
.createWith(recorder.mutinyDB2Pool(poolFunction))
.setRuntimeInit();

addQualifiers(mutinyDB2PoolConfigurator, dataSourceName);

syntheticBeans.produce(mutinyDB2PoolConfigurator.done());
}

vertxPool.produce(new VertxPoolBuildItem(pool, DatabaseKind.DB2, DataSourceUtil.isDefault(dataSourceName)));
private AnnotationInstance[] injectionPointAnnotations(String dataSourceName) {
if (DataSourceUtil.isDefault(dataSourceName)) {
return EMPTY_ANNOTATIONS;
}
return new AnnotationInstance[] {
AnnotationInstance.builder(REACTIVE_DATASOURCE).add("value", dataSourceName).build() };
}

private static boolean isReactiveDB2PoolDefined(DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.util.TypeLiteral;

import org.jboss.logging.Logger;

import io.quarkus.arc.Arc;
import io.quarkus.arc.SyntheticCreationalContext;
import io.quarkus.credentials.CredentialsProvider;
import io.quarkus.credentials.runtime.CredentialsProviderFinder;
import io.quarkus.datasource.common.runtime.DataSourceUtil;
Expand All @@ -44,43 +46,58 @@
public class DB2PoolRecorder {

private static final Logger log = Logger.getLogger(DB2PoolRecorder.class);
private static final TypeLiteral<Instance<DB2PoolCreator>> TYPE_LITERAL = new TypeLiteral<>() {
};

public RuntimeValue<DB2Pool> configureDB2Pool(RuntimeValue<Vertx> vertx,
public Function<SyntheticCreationalContext<DB2Pool>, DB2Pool> configureDB2Pool(RuntimeValue<Vertx> vertx,
Supplier<Integer> eventLoopCount,
String dataSourceName,
DataSourcesRuntimeConfig dataSourcesRuntimeConfig,
DataSourcesReactiveRuntimeConfig dataSourcesReactiveRuntimeConfig,
DataSourcesReactiveDB2Config dataSourcesReactiveDB2Config,
ShutdownContext shutdown) {

DB2Pool db2Pool = initialize((VertxInternal) vertx.getValue(),
eventLoopCount.get(),
dataSourceName,
dataSourcesRuntimeConfig.dataSources().get(dataSourceName),
dataSourcesReactiveRuntimeConfig.getDataSourceReactiveRuntimeConfig(dataSourceName),
dataSourcesReactiveDB2Config.dataSources().get(dataSourceName).reactive().db2());

shutdown.addShutdownTask(db2Pool::close);
return new RuntimeValue<>(db2Pool);
return new Function<>() {
@Override
public DB2Pool apply(SyntheticCreationalContext<DB2Pool> context) {
DB2Pool db2Pool = initialize((VertxInternal) vertx.getValue(),
eventLoopCount.get(),
dataSourceName,
dataSourcesRuntimeConfig.dataSources().get(dataSourceName),
dataSourcesReactiveRuntimeConfig.getDataSourceReactiveRuntimeConfig(dataSourceName),
dataSourcesReactiveDB2Config.dataSources().get(dataSourceName).reactive().db2(),
context);

shutdown.addShutdownTask(db2Pool::close);
return db2Pool;
}
};
}

public RuntimeValue<io.vertx.mutiny.db2client.DB2Pool> mutinyDB2Pool(RuntimeValue<DB2Pool> db2Pool) {
return new RuntimeValue<>(io.vertx.mutiny.db2client.DB2Pool.newInstance(db2Pool.getValue()));
public Function<SyntheticCreationalContext<io.vertx.mutiny.db2client.DB2Pool>, io.vertx.mutiny.db2client.DB2Pool> mutinyDB2Pool(
Function<SyntheticCreationalContext<DB2Pool>, DB2Pool> function) {
return new Function<>() {
@SuppressWarnings("unchecked")
@Override
public io.vertx.mutiny.db2client.DB2Pool apply(SyntheticCreationalContext context) {
return io.vertx.mutiny.db2client.DB2Pool.newInstance(function.apply(context));
}
};
}

private DB2Pool initialize(VertxInternal vertx,
Integer eventLoopCount,
String dataSourceName,
DataSourceRuntimeConfig dataSourceRuntimeConfig,
DataSourceReactiveRuntimeConfig dataSourceReactiveRuntimeConfig,
DataSourceReactiveDB2Config dataSourceReactiveDB2Config) {
DataSourceReactiveDB2Config dataSourceReactiveDB2Config,
SyntheticCreationalContext<DB2Pool> context) {
PoolOptions poolOptions = toPoolOptions(eventLoopCount, dataSourceRuntimeConfig, dataSourceReactiveRuntimeConfig,
dataSourceReactiveDB2Config);
DB2ConnectOptions db2ConnectOptions = toConnectOptions(dataSourceName, dataSourceRuntimeConfig,
dataSourceReactiveRuntimeConfig, dataSourceReactiveDB2Config);
Supplier<Future<DB2ConnectOptions>> databasesSupplier = toDatabasesSupplier(vertx, List.of(db2ConnectOptions),
dataSourceRuntimeConfig);
return createPool(vertx, poolOptions, db2ConnectOptions, dataSourceName, databasesSupplier);
return createPool(vertx, poolOptions, db2ConnectOptions, dataSourceName, databasesSupplier, context);
}

private Supplier<Future<DB2ConnectOptions>> toDatabasesSupplier(Vertx vertx, List<DB2ConnectOptions> db2ConnectOptionsList,
Expand Down Expand Up @@ -213,12 +230,13 @@ private DB2ConnectOptions toConnectOptions(String dataSourceName, DataSourceRunt
}

private DB2Pool createPool(Vertx vertx, PoolOptions poolOptions, DB2ConnectOptions dB2ConnectOptions,
String dataSourceName, Supplier<Future<DB2ConnectOptions>> databases) {
String dataSourceName, Supplier<Future<DB2ConnectOptions>> databases,
SyntheticCreationalContext<DB2Pool> context) {
Instance<DB2PoolCreator> instance;
if (DataSourceUtil.isDefault(dataSourceName)) {
instance = Arc.container().select(DB2PoolCreator.class);
instance = context.getInjectedReference(TYPE_LITERAL);
} else {
instance = Arc.container().select(DB2PoolCreator.class,
instance = context.getInjectedReference(TYPE_LITERAL,
new ReactiveDataSource.ReactiveDataSourceLiteral(dataSourceName));
}
if (instance.isResolvable()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package io.quarkus.reactive.mssql.client.deployment;

import java.util.function.Function;

import io.quarkus.arc.SyntheticCreationalContext;
import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.datasource.common.runtime.DataSourceUtil;
import io.quarkus.runtime.RuntimeValue;
import io.vertx.mssqlclient.MSSQLPool;

public final class MSSQLPoolBuildItem extends MultiBuildItem {

private final String dataSourceName;

private final RuntimeValue<MSSQLPool> mssqlPool;
private final Function<SyntheticCreationalContext<MSSQLPool>, MSSQLPool> mssqlPool;

public MSSQLPoolBuildItem(String dataSourceName, RuntimeValue<MSSQLPool> mssqlPool) {
public MSSQLPoolBuildItem(String dataSourceName, Function<SyntheticCreationalContext<MSSQLPool>, MSSQLPool> mssqlPool) {
this.dataSourceName = dataSourceName;
this.mssqlPool = mssqlPool;
}
Expand All @@ -20,7 +22,7 @@ public String getDataSourceName() {
return dataSourceName;
}

public RuntimeValue<MSSQLPool> getMSSQLPool() {
public Function<SyntheticCreationalContext<MSSQLPool>, MSSQLPool> getMSSQLPool() {
return mssqlPool;
}

Expand Down
Loading

0 comments on commit dc050e5

Please sign in to comment.