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 ee3e64b
Show file tree
Hide file tree
Showing 16 changed files with 342 additions and 201 deletions.

This file was deleted.

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 @@ -43,15 +48,13 @@
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
import io.quarkus.reactive.datasource.ReactiveDataSource;
import io.quarkus.reactive.datasource.deployment.VertxPoolBuildItem;
import io.quarkus.reactive.datasource.runtime.DataSourceReactiveBuildTimeConfig;
import io.quarkus.reactive.datasource.runtime.DataSourcesReactiveBuildTimeConfig;
import io.quarkus.reactive.datasource.runtime.DataSourcesReactiveRuntimeConfig;
import io.quarkus.reactive.db2.client.DB2PoolCreator;
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,11 +63,16 @@

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,
BuildProducer<DB2PoolBuildItem> db2Pool,
BuildProducer<VertxPoolBuildItem> vertxPool,
DB2PoolRecorder recorder,
VertxBuildItem vertx,
EventLoopCountBuildItem eventLoopCount,
Expand All @@ -81,7 +89,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 Down Expand Up @@ -168,7 +176,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 +191,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 +217,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 ee3e64b

Please sign in to comment.