Skip to content

Commit 98942f6

Browse files
authored
Merge pull request #46015 from tsegismont/sql-pool-migration
SqlClient pool migration
2 parents 3555cbc + a07d65d commit 98942f6

File tree

91 files changed

+578
-430
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+578
-430
lines changed

docs/src/main/asciidoc/reactive-sql-clients.adoc

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ package org.acme.reactive.crud;
4444
4545
import io.smallrye.mutiny.Multi;
4646
import io.smallrye.mutiny.Uni;
47-
import io.vertx.mutiny.pgclient.PgPool;
47+
import io.vertx.mutiny.sqlclient.Pool;
4848
import io.vertx.mutiny.sqlclient.Row;
4949
import io.vertx.mutiny.sqlclient.RowSet;
5050
import io.vertx.mutiny.sqlclient.Tuple;
@@ -179,7 +179,7 @@ quarkus.datasource.password=quarkus_test
179179
quarkus.datasource.reactive.url=postgresql://localhost:5432/quarkus_test
180180
----
181181

182-
With that you can create your `FruitResource` skeleton and inject a `io.vertx.mutiny.pgclient.PgPool` instance:
182+
With that you can create your `FruitResource` skeleton and inject a `io.vertx.mutiny.sqlclient.Pool` instance:
183183

184184
[source,java]
185185
.src/main/java/org/acme/vertx/FruitResource.java
@@ -199,14 +199,14 @@ import jakarta.ws.rs.core.Response.Status;
199199
200200
import io.smallrye.mutiny.Multi;
201201
import io.smallrye.mutiny.Uni;
202-
import io.vertx.mutiny.pgclient.PgPool;
202+
import io.vertx.mutiny.sqlclient.Pool;
203203
204204
@Path("fruits")
205205
public class FruitResource {
206206
207-
private final PgPool client;
207+
private final Pool client;
208208
209-
public FruitResource(PgPool client) {
209+
public FruitResource(Pool client) {
210210
this.client = client;
211211
}
212212
}
@@ -226,7 +226,7 @@ But for development we can simply drop and create the tables on startup, and the
226226
package org.acme.reactive.crud;
227227
228228
import io.quarkus.runtime.StartupEvent;
229-
import io.vertx.mutiny.pgclient.PgPool;
229+
import io.vertx.mutiny.sqlclient.Pool;
230230
import org.eclipse.microprofile.config.inject.ConfigProperty;
231231
232232
import jakarta.enterprise.context.ApplicationScoped;
@@ -235,10 +235,10 @@ import jakarta.enterprise.event.Observes;
235235
@ApplicationScoped
236236
public class DBInit {
237237
238-
private final PgPool client;
238+
private final Pool client;
239239
private final boolean schemaCreate;
240240
241-
public DBInit(PgPool client, @ConfigProperty(name = "myapp.schema.create", defaultValue = "true") boolean schemaCreate) {
241+
public DBInit(Pool client, @ConfigProperty(name = "myapp.schema.create", defaultValue = "true") boolean schemaCreate) {
242242
this.client = client;
243243
this.schemaCreate = schemaCreate;
244244
}
@@ -293,7 +293,7 @@ To retrieve all the data, we will use the `query` method again:
293293
[source,java]
294294
./src/main/java/org/acme/reactive/crud/Fruit.java
295295
----
296-
public static Multi<Fruit> findAll(PgPool client) {
296+
public static Multi<Fruit> findAll(Pool client) {
297297
return client.query("SELECT id, name FROM fruits ORDER BY name ASC").execute()
298298
.onItem().transformToMulti(set -> Multi.createFrom().iterable(set)) // <1>
299299
.onItem().transform(Fruit::from); // <2>
@@ -350,7 +350,7 @@ Equipped with this tooling, we are able to safely use an `id` provided by the us
350350
[source,java]
351351
.src/main/java/org/acme/vertx/Fruit.java
352352
----
353-
public static Uni<Fruit> findById(PgPool client, Long id) {
353+
public static Uni<Fruit> findById(Pool client, Long id) {
354354
return client.preparedQuery("SELECT id, name FROM fruits WHERE id = $1").execute(Tuple.of(id)) // <1>
355355
.onItem().transform(RowSet::iterator) // <2>
356356
.onItem().transform(iterator -> iterator.hasNext() ? from(iterator.next()) : null); // <3>
@@ -381,7 +381,7 @@ The same logic applies when saving a `Fruit`:
381381
[source,java]
382382
.src/main/java/org/acme/vertx/Fruit.java
383383
----
384-
public Uni<Long> save(PgPool client) {
384+
public Uni<Long> save(Pool client) {
385385
return client.preparedQuery("INSERT INTO fruits (name) VALUES ($1) RETURNING id").execute(Tuple.of(name))
386386
.onItem().transform(pgRowSet -> pgRowSet.iterator().next().getLong("id"));
387387
}
@@ -412,7 +412,7 @@ Let's use this to support removal of fruits in the database:
412412
[source,java]
413413
.src/main/java/org/acme/vertx/Fruit.java
414414
----
415-
public static Uni<Boolean> delete(PgPool client, Long id) {
415+
public static Uni<Boolean> delete(Pool client, Long id) {
416416
return client.preparedQuery("DELETE FROM fruits WHERE id = $1").execute(Tuple.of(id))
417417
.onItem().transform(pgRowSet -> pgRowSet.rowCount() == 1); // <1>
418418
}
@@ -524,33 +524,28 @@ Navigate to http://localhost:8080/fruits.html and read/create/delete some fruits
524524
[[reactive-sql-clients-details]]
525525
== Database Clients details
526526

527-
[cols="10,40,40,10"]
527+
[cols="15,70,15"]
528528
|===
529-
|Database |Extension name |Pool class name |Placeholders
529+
|Database |Extension name |Placeholders
530530

531531
|IBM Db2
532532
|`quarkus-reactive-db2-client`
533-
|`io.vertx.mutiny.db2client.DB2Pool`
534533
|`?`
535534

536535
|MariaDB/MySQL
537536
|`quarkus-reactive-mysql-client`
538-
|`io.vertx.mutiny.mysqlclient.MySQLPool`
539537
|`?`
540538

541539
|Microsoft SQL Server
542540
|`quarkus-reactive-mssql-client`
543-
|`io.vertx.mutiny.mssqlclient.MSSQLPool`
544541
|`@p1`, `@p2`, etc.
545542

546543
|Oracle
547544
|`quarkus-reactive-oracle-client`
548-
|`io.vertx.mutiny.oracleclient.OraclePool`
549545
|`?`
550546

551547
|PostgreSQL
552548
|`quarkus-reactive-pg-client`
553-
|`io.vertx.mutiny.pgclient.PgPool`
554549
|`$1`, `$2`, etc.
555550
|===
556551

@@ -570,7 +565,7 @@ The following snippet shows how to run 2 insertions in the same transaction:
570565

571566
[source, java]
572567
----
573-
public static Uni<Void> insertTwoFruits(PgPool client, Fruit fruit1, Fruit fruit2) {
568+
public static Uni<Void> insertTwoFruits(Pool client, Fruit fruit1, Fruit fruit2) {
574569
return client.withTransaction(conn -> {
575570
Uni<RowSet<Row>> insertOne = conn.preparedQuery("INSERT INTO fruits (name) VALUES ($1) RETURNING id")
576571
.execute(Tuple.of(fruit1.name));
@@ -691,11 +686,11 @@ You can then inject the clients as follows:
691686
[source,java]
692687
----
693688
@Inject <1>
694-
PgPool defaultClient;
689+
Pool defaultClient;
695690
696691
@Inject
697692
@ReactiveDataSource("additional1") <2>
698-
PgPool additional1Client;
693+
Pool additional1Client;
699694
700695
@Inject
701696
@ReactiveDataSource("additional2")
@@ -830,18 +825,18 @@ import jakarta.inject.Singleton;
830825
831826
import io.quarkus.reactive.pg.client.PgPoolCreator;
832827
import io.vertx.pgclient.PgConnectOptions;
833-
import io.vertx.pgclient.PgPool;
828+
import io.vertx.sqlclient.Pool;
834829
import io.vertx.sqlclient.PoolOptions;
835830
836831
@Singleton
837832
public class CustomPgPoolCreator implements PgPoolCreator {
838833
839834
@Override
840-
public PgPool create(Input input) {
835+
public Pool create(Input input) {
841836
PgConnectOptions connectOptions = input.pgConnectOptions();
842837
PoolOptions poolOptions = input.poolOptions();
843838
// Customize connectOptions, poolOptions or both, as required
844-
return PgPool.pool(input.vertx(), connectOptions, poolOptions);
839+
return Pool.pool(input.vertx(), connectOptions, poolOptions);
845840
}
846841
}
847842
----
@@ -860,12 +855,12 @@ Here's an example for PostgreSQL:
860855
import jakarta.inject.Inject;
861856
862857
import io.smallrye.mutiny.Uni;
863-
import io.vertx.mutiny.pgclient.PgPool;
858+
import io.vertx.mutiny.sqlclient.Pool;
864859
865860
public class PipeliningExample {
866861
867862
@Inject
868-
PgPool client;
863+
Pool client;
869864
870865
public Uni<String> favoriteFruitAndVegetable() {
871866
// Explicitly acquire a connection

extensions/reactive-datasource/deployment/src/main/java/io/quarkus/reactive/datasource/deployment/ReactiveDataSourceBuildUtil.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
import jakarta.enterprise.inject.Default;
44

55
import org.jboss.jandex.AnnotationInstance;
6+
import org.jboss.jandex.ClassType;
7+
import org.jboss.jandex.Type;
68

79
import io.quarkus.arc.processor.DotNames;
810
import io.quarkus.datasource.common.runtime.DataSourceUtil;
911
import io.quarkus.reactive.datasource.ReactiveDataSource;
1012

1113
public final class ReactiveDataSourceBuildUtil {
14+
15+
public static final Type VERTX_POOL_TYPE = ClassType.create(ReactiveDataSourceDotNames.VERTX_POOL);
16+
1217
private ReactiveDataSourceBuildUtil() {
1318
}
1419

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.quarkus.reactive.datasource.deployment;
2+
3+
import jakarta.enterprise.inject.Instance;
4+
5+
import org.jboss.jandex.DotName;
6+
7+
import io.vertx.sqlclient.Pool;
8+
9+
public class ReactiveDataSourceDotNames {
10+
11+
public static final DotName VERTX_POOL = DotName.createSimple(Pool.class);
12+
public static final DotName INJECT_INSTANCE = DotName.createSimple(Instance.class);
13+
14+
private ReactiveDataSourceDotNames() {
15+
//Utility
16+
}
17+
}

extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/ReactiveDatasourceHealthCheck.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,16 @@ public HealthCheckResponse call() {
4646
HealthCheckResponseBuilder builder = HealthCheckResponse.named(healthCheckResponseName);
4747
builder.up();
4848

49-
for (Map.Entry<String, Pool> pgPoolEntry : pools.entrySet()) {
50-
final String dataSourceName = pgPoolEntry.getKey();
51-
final Pool pgPool = pgPoolEntry.getValue();
49+
for (Map.Entry<String, Pool> poolEntry : pools.entrySet()) {
50+
final String dataSourceName = poolEntry.getKey();
51+
final Pool pool = poolEntry.getValue();
5252
try {
5353
CompletableFuture<Void> databaseConnectionAttempt = new CompletableFuture<>();
5454
Context context = Vertx.currentContext();
5555
if (context != null) {
5656
log.debug("Run health check on the current Vert.x context");
5757
context.runOnContext(v -> {
58-
pgPool.query(healthCheckSQL)
58+
pool.query(healthCheckSQL)
5959
.execute(ar -> {
6060
checkFailure(ar, builder, dataSourceName);
6161
databaseConnectionAttempt.complete(null);
@@ -64,7 +64,7 @@ public HealthCheckResponse call() {
6464
} else {
6565
log.warn("Vert.x context unavailable to perform health check of reactive datasource `" + dataSourceName
6666
+ "`. This is unlikely to work correctly.");
67-
pgPool.query(healthCheckSQL)
67+
pool.query(healthCheckSQL)
6868
.execute(ar -> {
6969
checkFailure(ar, builder, dataSourceName);
7070
databaseConnectionAttempt.complete(null);

extensions/reactive-db2-client/deployment/src/main/java/io/quarkus/reactive/db2/client/deployment/DB2PoolBuildItem.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.quarkus.datasource.common.runtime.DataSourceUtil;
88
import io.vertx.db2client.DB2Pool;
99

10+
@Deprecated(forRemoval = true)
1011
public final class DB2PoolBuildItem extends MultiBuildItem {
1112

1213
private final String dataSourceName;

extensions/reactive-db2-client/deployment/src/main/java/io/quarkus/reactive/db2/client/deployment/ReactiveDB2ClientProcessor.java

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import static io.quarkus.reactive.datasource.deployment.ReactiveDataSourceBuildUtil.qualifier;
44
import static io.quarkus.reactive.datasource.deployment.ReactiveDataSourceBuildUtil.qualifiers;
5+
import static io.quarkus.reactive.datasource.deployment.ReactiveDataSourceDotNames.INJECT_INSTANCE;
6+
import static java.util.stream.Collectors.toSet;
57

68
import java.util.HashMap;
79
import java.util.List;
@@ -12,9 +14,10 @@
1214
import java.util.function.Function;
1315
import java.util.function.Predicate;
1416
import java.util.stream.Collectors;
17+
import java.util.stream.Stream;
1518

1619
import jakarta.enterprise.context.ApplicationScoped;
17-
import jakarta.enterprise.inject.Instance;
20+
import jakarta.inject.Singleton;
1821

1922
import org.jboss.jandex.AnnotationInstance;
2023
import org.jboss.jandex.ClassType;
@@ -55,6 +58,7 @@
5558
import io.quarkus.reactive.datasource.runtime.DataSourcesReactiveRuntimeConfig;
5659
import io.quarkus.reactive.db2.client.DB2PoolCreator;
5760
import io.quarkus.reactive.db2.client.runtime.DB2PoolRecorder;
61+
import io.quarkus.reactive.db2.client.runtime.DB2PoolSupport;
5862
import io.quarkus.reactive.db2.client.runtime.DB2ServiceBindingConverter;
5963
import io.quarkus.reactive.db2.client.runtime.DataSourcesReactiveDB2Config;
6064
import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem;
@@ -65,12 +69,12 @@
6569

6670
class ReactiveDB2ClientProcessor {
6771

68-
private static final ParameterizedType POOL_CREATOR_INJECTION_TYPE = ParameterizedType.create(
69-
DotName.createSimple(Instance.class),
70-
new Type[] { ClassType.create(DotName.createSimple(DB2PoolCreator.class.getName())) }, null);
72+
private static final Type DB2_POOL_CREATOR = ClassType.create(DotName.createSimple(DB2PoolCreator.class.getName()));
73+
private static final ParameterizedType POOL_CREATOR_INJECTION_TYPE = ParameterizedType.create(INJECT_INSTANCE,
74+
new Type[] { DB2_POOL_CREATOR }, null);
7175

7276
private static final DotName VERTX_DB2_POOL = DotName.createSimple(DB2Pool.class);
73-
private static final Type VERTX_DB2_POOL_TYPE = Type.create(VERTX_DB2_POOL, Type.Kind.CLASS);
77+
private static final Type VERTX_DB2_POOL_TYPE = ClassType.create(VERTX_DB2_POOL);
7478

7579
@BuildStep
7680
@Record(ExecutionTime.RUNTIME_INIT)
@@ -92,11 +96,28 @@ ServiceStartBuildItem build(BuildProducer<FeatureBuildItem> feature,
9296

9397
feature.produce(new FeatureBuildItem(Feature.REACTIVE_DB2_CLIENT));
9498

99+
Stream.Builder<String> db2PoolNamesBuilder = Stream.builder();
95100
for (String dataSourceName : dataSourcesBuildTimeConfig.dataSources().keySet()) {
96-
createPoolIfDefined(recorder, vertx, eventLoopCount, shutdown, db2Pool, syntheticBeans, dataSourceName,
97-
dataSourcesBuildTimeConfig, dataSourcesRuntimeConfig, dataSourcesReactiveBuildTimeConfig,
98-
dataSourcesReactiveRuntimeConfig, dataSourcesReactiveDB2Config, defaultDataSourceDbKindBuildItems,
99-
curateOutcomeBuildItem);
101+
102+
if (!isReactiveDB2PoolDefined(dataSourcesBuildTimeConfig, dataSourcesReactiveBuildTimeConfig, dataSourceName,
103+
defaultDataSourceDbKindBuildItems, curateOutcomeBuildItem)) {
104+
continue;
105+
}
106+
107+
createPool(recorder, vertx, eventLoopCount, shutdown, db2Pool, syntheticBeans, dataSourceName,
108+
dataSourcesRuntimeConfig, dataSourcesReactiveRuntimeConfig, dataSourcesReactiveDB2Config);
109+
110+
db2PoolNamesBuilder.add(dataSourceName);
111+
}
112+
113+
Set<String> db2PoolNames = db2PoolNamesBuilder.build().collect(toSet());
114+
if (!db2PoolNames.isEmpty()) {
115+
syntheticBeans.produce(SyntheticBeanBuildItem.configure(DB2PoolSupport.class)
116+
.scope(Singleton.class)
117+
.unremovable()
118+
.runtimeValue(recorder.createDB2PoolSupport(db2PoolNames))
119+
.setRuntimeInit()
120+
.done());
100121
}
101122

102123
// Enable SSL support by default
@@ -176,25 +197,16 @@ void addHealthCheck(
176197
dataSourcesBuildTimeConfig.healthEnabled()));
177198
}
178199

179-
private void createPoolIfDefined(DB2PoolRecorder recorder,
200+
private void createPool(DB2PoolRecorder recorder,
180201
VertxBuildItem vertx,
181202
EventLoopCountBuildItem eventLoopCount,
182203
ShutdownContextBuildItem shutdown,
183204
BuildProducer<DB2PoolBuildItem> db2Pool,
184205
BuildProducer<SyntheticBeanBuildItem> syntheticBeans,
185206
String dataSourceName,
186-
DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig,
187207
DataSourcesRuntimeConfig dataSourcesRuntimeConfig,
188-
DataSourcesReactiveBuildTimeConfig dataSourcesReactiveBuildTimeConfig,
189208
DataSourcesReactiveRuntimeConfig dataSourcesReactiveRuntimeConfig,
190-
DataSourcesReactiveDB2Config dataSourcesReactiveDB2Config,
191-
List<DefaultDataSourceDbKindBuildItem> defaultDataSourceDbKindBuildItems,
192-
CurateOutcomeBuildItem curateOutcomeBuildItem) {
193-
194-
if (!isReactiveDB2PoolDefined(dataSourcesBuildTimeConfig, dataSourcesReactiveBuildTimeConfig, dataSourceName,
195-
defaultDataSourceDbKindBuildItems, curateOutcomeBuildItem)) {
196-
return;
197-
}
209+
DataSourcesReactiveDB2Config dataSourcesReactiveDB2Config) {
198210

199211
Function<SyntheticCreationalContext<DB2Pool>, DB2Pool> poolFunction = recorder.configureDB2Pool(vertx.getVertx(),
200212
eventLoopCount.getEventLoopCount(),
@@ -282,8 +294,6 @@ private boolean hasPools(DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig,
282294
}
283295

284296
private static class DB2PoolCreatorBeanClassPredicate implements Predicate<Set<Type>> {
285-
private static final Type DB2_POOL_CREATOR = Type.create(DotName.createSimple(DB2PoolCreator.class.getName()),
286-
Type.Kind.CLASS);
287297

288298
@Override
289299
public boolean test(Set<Type> types) {

0 commit comments

Comments
 (0)