From 737b98240aa007dd54f518a3748799e212d0c186 Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Thu, 1 Jul 2021 17:10:06 +0200 Subject: [PATCH 1/7] MS SQL extension - runtime/deployment modules - integration tests (including native mode) - datasources docs --- .github/quarkus-bot.yml | 2 + bom/application/pom.xml | 10 + .../java/io/quarkus/deployment/Feature.java | 1 + devtools/bom-descriptor-json/pom.xml | 13 + docs/pom.xml | 13 + .../main/asciidoc/credentials-provider.adoc | 1 + docs/src/main/asciidoc/datasource.adoc | 4 + extensions/pom.xml | 1 + .../reactive-mssql-client/deployment/pom.xml | 200 +++++++++++++++ .../client/deployment/MSSQLPoolBuildItem.java | 31 +++ .../ReactiveMSSQLClientProcessor.java | 205 +++++++++++++++ .../mssql/client/CredentialsTest.java | 31 +++ .../mssql/client/CredentialsTestResource.java | 34 +++ .../client/CustomCredentialsProvider.java | 27 ++ .../mssql/client/DevModeResource.java | 42 +++ .../mssql/client/MSSQLPoolProducerTest.java | 66 +++++ .../mssql/client/MultipleDataSourcesTest.java | 79 ++++++ .../mssql/client/ReactiveMSSQLReloadTest.java | 39 +++ .../application-credentials.properties | 3 + .../application-default-datasource.properties | 2 + ...pplication-multiple-datasources.properties | 9 + extensions/reactive-mssql-client/pom.xml | 25 ++ .../reactive-mssql-client/runtime/pom.xml | 66 +++++ .../DataSourceReactiveMSSQLConfig.java | 8 + .../DataSourcesReactiveMSSQLConfig.java | 62 +++++ .../client/runtime/MSSQLPoolRecorder.java | 134 ++++++++++ .../ReactiveMSSQLDataSourcesHealthCheck.java | 29 +++ .../resources/META-INF/quarkus-extension.yaml | 17 ++ integration-tests/pom.xml | 1 + .../reactive-mssql-client/README.md | 28 ++ .../reactive-mssql-client/pom.xml | 239 ++++++++++++++++++ .../reactive/mssql/client/FruitResource.java | 51 ++++ .../src/main/resources/application.properties | 4 + .../mssql/client/FruitsEndpointTest.java | 25 ++ .../reactive/mssql/client/HealthCheckIT.java | 7 + .../mssql/client/HealthCheckTest.java | 24 ++ .../mssql/client/HotReloadFruitResource.java | 51 ++++ .../mssql/client/NativeFruitsEndpointIT.java | 10 + .../test/resources/application-tl.properties | 5 + 39 files changed, 1599 insertions(+) create mode 100644 extensions/reactive-mssql-client/deployment/pom.xml create mode 100644 extensions/reactive-mssql-client/deployment/src/main/java/io/quarkus/reactive/mssql/client/deployment/MSSQLPoolBuildItem.java create mode 100644 extensions/reactive-mssql-client/deployment/src/main/java/io/quarkus/reactive/mssql/client/deployment/ReactiveMSSQLClientProcessor.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CredentialsTest.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CredentialsTestResource.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CustomCredentialsProvider.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DevModeResource.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/MSSQLPoolProducerTest.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/MultipleDataSourcesTest.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ReactiveMSSQLReloadTest.java create mode 100644 extensions/reactive-mssql-client/deployment/src/test/resources/application-credentials.properties create mode 100644 extensions/reactive-mssql-client/deployment/src/test/resources/application-default-datasource.properties create mode 100644 extensions/reactive-mssql-client/deployment/src/test/resources/application-multiple-datasources.properties create mode 100644 extensions/reactive-mssql-client/pom.xml create mode 100644 extensions/reactive-mssql-client/runtime/pom.xml create mode 100644 extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourceReactiveMSSQLConfig.java create mode 100644 extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourcesReactiveMSSQLConfig.java create mode 100644 extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java create mode 100644 extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/health/ReactiveMSSQLDataSourcesHealthCheck.java create mode 100644 extensions/reactive-mssql-client/runtime/src/main/resources/META-INF/quarkus-extension.yaml create mode 100644 integration-tests/reactive-mssql-client/README.md create mode 100644 integration-tests/reactive-mssql-client/pom.xml create mode 100644 integration-tests/reactive-mssql-client/src/main/java/io/quarkus/it/reactive/mssql/client/FruitResource.java create mode 100644 integration-tests/reactive-mssql-client/src/main/resources/application.properties create mode 100644 integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/FruitsEndpointTest.java create mode 100644 integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HealthCheckIT.java create mode 100644 integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HealthCheckTest.java create mode 100644 integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HotReloadFruitResource.java create mode 100644 integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/NativeFruitsEndpointIT.java create mode 100644 integration-tests/reactive-mssql-client/src/test/resources/application-tl.properties diff --git a/.github/quarkus-bot.yml b/.github/quarkus-bot.yml index 7ca63fe7100fe..1ba57d39e7c72 100644 --- a/.github/quarkus-bot.yml +++ b/.github/quarkus-bot.yml @@ -476,9 +476,11 @@ triage: directories: - extensions/reactive-db2-client/ - extensions/reactive-mysql-client/ + - extensions/reactive-mssql-client/ - extensions/reactive-pg-client/ - integration-tests/reactive-db2-client/ - integration-tests/reactive-mysql-client/ + - integration-tests/reactive-mssql-client/ - integration-tests/reactive-pg-client/ - labels: [area/adr] title: "adr" diff --git a/bom/application/pom.xml b/bom/application/pom.xml index 2ef9e8c7457a9..69a2c5a2ecb37 100644 --- a/bom/application/pom.xml +++ b/bom/application/pom.xml @@ -1577,6 +1577,16 @@ quarkus-reactive-mysql-client-deployment ${project.version} + + io.quarkus + quarkus-reactive-mssql-client + ${project.version} + + + io.quarkus + quarkus-reactive-mssql-client-deployment + ${project.version} + io.quarkus quarkus-mailer diff --git a/core/deployment/src/main/java/io/quarkus/deployment/Feature.java b/core/deployment/src/main/java/io/quarkus/deployment/Feature.java index 06d92019c9433..187074ae82217 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/Feature.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/Feature.java @@ -87,6 +87,7 @@ public enum Feature { QUTE, REACTIVE_PG_CLIENT, REACTIVE_MYSQL_CLIENT, + REACTIVE_MSSQL_CLIENT, REACTIVE_DB2_CLIENT, REDIS_CLIENT, RESTEASY, diff --git a/devtools/bom-descriptor-json/pom.xml b/devtools/bom-descriptor-json/pom.xml index 236d3db391dba..bea45061dfdaf 100644 --- a/devtools/bom-descriptor-json/pom.xml +++ b/devtools/bom-descriptor-json/pom.xml @@ -1813,6 +1813,19 @@ + + io.quarkus + quarkus-reactive-mssql-client + ${project.version} + pom + test + + + * + * + + + io.quarkus quarkus-reactive-pg-client diff --git a/docs/pom.xml b/docs/pom.xml index 020374c622e60..cfdd6b7c677fb 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -1774,6 +1774,19 @@ + + io.quarkus + quarkus-reactive-mssql-client-deployment + ${project.version} + pom + test + + + * + * + + + io.quarkus quarkus-reactive-pg-client-deployment diff --git a/docs/src/main/asciidoc/credentials-provider.adoc b/docs/src/main/asciidoc/credentials-provider.adoc index c2cc766280007..584eec4b9d55c 100644 --- a/docs/src/main/asciidoc/credentials-provider.adoc +++ b/docs/src/main/asciidoc/credentials-provider.adoc @@ -31,6 +31,7 @@ by the following credentials consumer extensions: * `agroal` * `reactive-db2-client` * `reactive-mysql-client` +* `reactive-mssql-client` * `reactive-pg-client` * `oidc` * `oidc-client` diff --git a/docs/src/main/asciidoc/datasource.adoc b/docs/src/main/asciidoc/datasource.adoc index c91753e159181..0ed28de56feed 100644 --- a/docs/src/main/asciidoc/datasource.adoc +++ b/docs/src/main/asciidoc/datasource.adoc @@ -662,6 +662,10 @@ include::{generated-dir}/config/quarkus-reactive-db2-client.adoc[opts=optional, include::{generated-dir}/config/quarkus-reactive-mysql-client.adoc[opts=optional, leveloffset=+1] +=== Reactive MS SQL Specific Configuration + +include::{generated-dir}/config/quarkus-reactive-mssql-client.adoc[opts=optional, leveloffset=+1] + === Reactive PostgreSQL Specific Configuration include::{generated-dir}/config/quarkus-reactive-pg-client.adoc[opts=optional, leveloffset=+1] diff --git a/extensions/pom.xml b/extensions/pom.xml index b58c115b2984a..5a8b3e477ed93 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -70,6 +70,7 @@ reactive-db2-client reactive-pg-client reactive-mysql-client + reactive-mssql-client mailer grpc redis-client diff --git a/extensions/reactive-mssql-client/deployment/pom.xml b/extensions/reactive-mssql-client/deployment/pom.xml new file mode 100644 index 0000000000000..278a3d9dc9898 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/pom.xml @@ -0,0 +1,200 @@ + + + 4.0.0 + + + io.quarkus + quarkus-reactive-mssql-client-parent + 999-SNAPSHOT + + + quarkus-reactive-mssql-client-deployment + + Quarkus - Reactive MS SQL Client - Deployment + + + vertx-reactive:sqlserver://localhost:1433 + mcr.microsoft.com/mssql/server:2019-latest + + + + + io.quarkus + quarkus-reactive-datasource-deployment + + + io.quarkus + quarkus-vertx-deployment + + + io.quarkus + quarkus-credentials-deployment + + + io.quarkus + quarkus-reactive-mssql-client + + + io.quarkus + quarkus-smallrye-health-spi + + + + io.quarkus + quarkus-resteasy-deployment + test + + + io.rest-assured + rest-assured + test + + + io.quarkus + quarkus-junit5-internal + test + + + + + + + src/test/resources + true + + + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + maven-surefire-plugin + + true + + + + + + + + test-mssql + + + test-containers + + + + + + maven-surefire-plugin + + false + + + + + + + docker-mssql + + + start-containers + + + + vertx-reactive:sqlserver://localhost:1435 + + + + + io.fabric8 + docker-maven-plugin + + + + ${mssql.image} + quarkus-test-mssql + + + bridge + + + 1435:1433 + + + Y + A_Str0ng_Required_Password + + + MSSQL: + default + cyan + + + + + direct + + 1433 + + + + + + + + true + + + + docker-start + compile + + stop + start + + + + docker-stop + post-integration-test + + stop + + + + + + org.codehaus.mojo + exec-maven-plugin + + + docker-prune + generate-resources + + exec + + + ${docker-prune.location} + + + + + + + + + + diff --git a/extensions/reactive-mssql-client/deployment/src/main/java/io/quarkus/reactive/mssql/client/deployment/MSSQLPoolBuildItem.java b/extensions/reactive-mssql-client/deployment/src/main/java/io/quarkus/reactive/mssql/client/deployment/MSSQLPoolBuildItem.java new file mode 100644 index 0000000000000..0eb56a6071d9d --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/main/java/io/quarkus/reactive/mssql/client/deployment/MSSQLPoolBuildItem.java @@ -0,0 +1,31 @@ +package io.quarkus.reactive.mssql.client.deployment; + +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; + + public MSSQLPoolBuildItem(String dataSourceName, RuntimeValue mssqlPool) { + this.dataSourceName = dataSourceName; + this.mssqlPool = mssqlPool; + } + + public String getDataSourceName() { + return dataSourceName; + } + + public RuntimeValue getMSSQLPool() { + return mssqlPool; + } + + public boolean isDefault() { + return DataSourceUtil.isDefault(dataSourceName); + } + +} diff --git a/extensions/reactive-mssql-client/deployment/src/main/java/io/quarkus/reactive/mssql/client/deployment/ReactiveMSSQLClientProcessor.java b/extensions/reactive-mssql-client/deployment/src/main/java/io/quarkus/reactive/mssql/client/deployment/ReactiveMSSQLClientProcessor.java new file mode 100644 index 0000000000000..8509fe4ed4116 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/main/java/io/quarkus/reactive/mssql/client/deployment/ReactiveMSSQLClientProcessor.java @@ -0,0 +1,205 @@ +package io.quarkus.reactive.mssql.client.deployment; + +import java.util.List; +import java.util.Optional; + +import javax.enterprise.context.ApplicationScoped; + +import io.quarkus.arc.deployment.SyntheticBeanBuildItem; +import io.quarkus.arc.deployment.SyntheticBeanBuildItem.ExtendedBeanConfigurator; +import io.quarkus.arc.processor.DotNames; +import io.quarkus.datasource.common.runtime.DataSourceUtil; +import io.quarkus.datasource.common.runtime.DatabaseKind; +import io.quarkus.datasource.deployment.spi.DefaultDataSourceDbKindBuildItem; +import io.quarkus.datasource.runtime.DataSourceBuildTimeConfig; +import io.quarkus.datasource.runtime.DataSourcesBuildTimeConfig; +import io.quarkus.datasource.runtime.DataSourcesRuntimeConfig; +import io.quarkus.deployment.Feature; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.annotations.ExecutionTime; +import io.quarkus.deployment.annotations.Record; +import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.ServiceStartBuildItem; +import io.quarkus.deployment.builditem.ShutdownContextBuildItem; +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.mssql.client.runtime.DataSourcesReactiveMSSQLConfig; +import io.quarkus.reactive.mssql.client.runtime.MSSQLPoolRecorder; +import io.quarkus.runtime.RuntimeValue; +import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem; +import io.quarkus.vertx.deployment.VertxBuildItem; +import io.vertx.mssqlclient.MSSQLPool; +import io.vertx.sqlclient.Pool; + +class ReactiveMSSQLClientProcessor { + + @BuildStep + @Record(ExecutionTime.RUNTIME_INIT) + ServiceStartBuildItem build(BuildProducer feature, + BuildProducer msSQLPool, + BuildProducer vertxPool, + MSSQLPoolRecorder recorder, + VertxBuildItem vertx, + ShutdownContextBuildItem shutdown, + BuildProducer syntheticBeans, + BuildProducer sslNativeSupport, + DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig, DataSourcesRuntimeConfig dataSourcesRuntimeConfig, + DataSourcesReactiveBuildTimeConfig dataSourcesReactiveBuildTimeConfig, + DataSourcesReactiveRuntimeConfig dataSourcesReactiveRuntimeConfig, + DataSourcesReactiveMSSQLConfig dataSourcesReactiveMSSQLConfig, + List defaultDataSourceDbKindBuildItems, + CurateOutcomeBuildItem curateOutcomeBuildItem) { + + feature.produce(new FeatureBuildItem(Feature.REACTIVE_MSSQL_CLIENT)); + + createPoolIfDefined(recorder, vertx, shutdown, msSQLPool, vertxPool, syntheticBeans, + DataSourceUtil.DEFAULT_DATASOURCE_NAME, dataSourcesBuildTimeConfig, + dataSourcesRuntimeConfig, dataSourcesReactiveBuildTimeConfig, dataSourcesReactiveRuntimeConfig, + dataSourcesReactiveMSSQLConfig, defaultDataSourceDbKindBuildItems, curateOutcomeBuildItem); + + for (String dataSourceName : dataSourcesBuildTimeConfig.namedDataSources.keySet()) { + createPoolIfDefined(recorder, vertx, shutdown, msSQLPool, vertxPool, syntheticBeans, dataSourceName, + dataSourcesBuildTimeConfig, dataSourcesRuntimeConfig, dataSourcesReactiveBuildTimeConfig, + dataSourcesReactiveRuntimeConfig, dataSourcesReactiveMSSQLConfig, defaultDataSourceDbKindBuildItems, + curateOutcomeBuildItem); + } + + return new ServiceStartBuildItem("reactive-mssql-client"); + } + + /** + * The health check needs to be produced in a separate method to avoid a circular dependency (the Vert.x instance creation + * consumes the AdditionalBeanBuildItems). + */ + @BuildStep + void addHealthCheck( + BuildProducer healthChecks, + DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig, + DataSourcesReactiveBuildTimeConfig dataSourcesReactiveBuildTimeConfig, + List defaultDataSourceDbKindBuildItems, + CurateOutcomeBuildItem curateOutcomeBuildItem) { + if (!hasPools(dataSourcesBuildTimeConfig, dataSourcesReactiveBuildTimeConfig, defaultDataSourceDbKindBuildItems, + curateOutcomeBuildItem)) { + return; + } + + healthChecks.produce( + new HealthBuildItem("io.quarkus.reactive.mssql.client.runtime.health.ReactiveMSSQLDataSourcesHealthCheck", + dataSourcesBuildTimeConfig.healthEnabled)); + } + + private void createPoolIfDefined(MSSQLPoolRecorder recorder, + VertxBuildItem vertx, + ShutdownContextBuildItem shutdown, + BuildProducer msSQLPool, + BuildProducer vertxPool, + BuildProducer syntheticBeans, + String dataSourceName, + DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig, + DataSourcesRuntimeConfig dataSourcesRuntimeConfig, + DataSourcesReactiveBuildTimeConfig dataSourcesReactiveBuildTimeConfig, + DataSourcesReactiveRuntimeConfig dataSourcesReactiveRuntimeConfig, + DataSourcesReactiveMSSQLConfig dataSourcesReactiveMSSQLConfig, + List defaultDataSourceDbKindBuildItems, + CurateOutcomeBuildItem curateOutcomeBuildItem) { + + if (!isReactiveMSSQLPoolDefined(dataSourcesBuildTimeConfig, dataSourcesReactiveBuildTimeConfig, dataSourceName, + defaultDataSourceDbKindBuildItems, curateOutcomeBuildItem)) { + return; + } + + RuntimeValue pool = recorder.configureMSSQLPool(vertx.getVertx(), + dataSourceName, + dataSourcesRuntimeConfig, + dataSourcesReactiveRuntimeConfig, + dataSourcesReactiveMSSQLConfig, + shutdown); + msSQLPool.produce(new MSSQLPoolBuildItem(dataSourceName, pool)); + + ExtendedBeanConfigurator msSQLPoolBeanConfigurator = SyntheticBeanBuildItem.configure(MSSQLPool.class) + .defaultBean() + .addType(Pool.class) + .scope(ApplicationScoped.class) + .runtimeValue(pool) + .unremovable() + .setRuntimeInit(); + + addQualifiers(msSQLPoolBeanConfigurator, dataSourceName); + + syntheticBeans.produce(msSQLPoolBeanConfigurator.done()); + + ExtendedBeanConfigurator mutinyMSSQLPoolConfigurator = SyntheticBeanBuildItem + .configure(io.vertx.mutiny.mssqlclient.MSSQLPool.class) + .defaultBean() + .scope(ApplicationScoped.class) + .runtimeValue(recorder.mutinyMSSQLPool(pool)) + .setRuntimeInit(); + + addQualifiers(mutinyMSSQLPoolConfigurator, dataSourceName); + + syntheticBeans.produce(mutinyMSSQLPoolConfigurator.done()); + + vertxPool.produce(new VertxPoolBuildItem(pool, DatabaseKind.MSSQL, DataSourceUtil.isDefault(dataSourceName))); + } + + private static boolean isReactiveMSSQLPoolDefined(DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig, + DataSourcesReactiveBuildTimeConfig dataSourcesReactiveBuildTimeConfig, String dataSourceName, + List defaultDataSourceDbKindBuildItems, + CurateOutcomeBuildItem curateOutcomeBuildItem) { + DataSourceBuildTimeConfig dataSourceBuildTimeConfig = dataSourcesBuildTimeConfig + .getDataSourceRuntimeConfig(dataSourceName); + DataSourceReactiveBuildTimeConfig dataSourceReactiveBuildTimeConfig = dataSourcesReactiveBuildTimeConfig + .getDataSourceReactiveBuildTimeConfig(dataSourceName); + + Optional dbKind = DefaultDataSourceDbKindBuildItem.resolve(dataSourceBuildTimeConfig.dbKind, + defaultDataSourceDbKindBuildItems, + !DataSourceUtil.isDefault(dataSourceName) || dataSourceBuildTimeConfig.devservices.enabled + .orElse(dataSourcesBuildTimeConfig.namedDataSources.isEmpty()), + curateOutcomeBuildItem); + if (!dbKind.isPresent()) { + return false; + } + + if (!DatabaseKind.isMsSQL(dbKind.get()) + || !dataSourceReactiveBuildTimeConfig.enabled) { + return false; + } + + return true; + } + + private boolean hasPools(DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig, + DataSourcesReactiveBuildTimeConfig dataSourcesReactiveBuildTimeConfig, + List defaultDataSourceDbKindBuildItems, + CurateOutcomeBuildItem curateOutcomeBuildItem) { + if (isReactiveMSSQLPoolDefined(dataSourcesBuildTimeConfig, dataSourcesReactiveBuildTimeConfig, + DataSourceUtil.DEFAULT_DATASOURCE_NAME, defaultDataSourceDbKindBuildItems, curateOutcomeBuildItem)) { + return true; + } + + for (String dataSourceName : dataSourcesBuildTimeConfig.namedDataSources.keySet()) { + if (isReactiveMSSQLPoolDefined(dataSourcesBuildTimeConfig, dataSourcesReactiveBuildTimeConfig, + dataSourceName, defaultDataSourceDbKindBuildItems, curateOutcomeBuildItem)) { + return true; + } + } + + return false; + } + + private static void addQualifiers(ExtendedBeanConfigurator configurator, String dataSourceName) { + if (DataSourceUtil.isDefault(dataSourceName)) { + configurator.addQualifier(DotNames.DEFAULT); + } else { + configurator.addQualifier().annotation(DotNames.NAMED).addValue("value", dataSourceName).done(); + configurator.addQualifier().annotation(ReactiveDataSource.class).addValue("value", dataSourceName) + .done(); + } + } +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CredentialsTest.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CredentialsTest.java new file mode 100644 index 0000000000000..77473b651e8e5 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CredentialsTest.java @@ -0,0 +1,31 @@ +package io.quarkus.reactive.mssql.client; + +import static io.restassured.RestAssured.given; + +import org.hamcrest.CoreMatchers; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; + +public class CredentialsTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClass(CustomCredentialsProvider.class) + .addClass(CredentialsTestResource.class) + .addAsResource("application-credentials.properties", "application.properties")); + + @Test + public void testConnect() { + given() + .when().get("/test") + .then() + .statusCode(200) + .body(CoreMatchers.equalTo("OK")); + } + +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CredentialsTestResource.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CredentialsTestResource.java new file mode 100644 index 0000000000000..19b27d85611c9 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CredentialsTestResource.java @@ -0,0 +1,34 @@ +package io.quarkus.reactive.mssql.client; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.concurrent.CompletionStage; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import io.vertx.mutiny.mssqlclient.MSSQLPool; + +@Path("/test") +public class CredentialsTestResource { + + @Inject + MSSQLPool client; + + @GET + @Produces(MediaType.TEXT_PLAIN) + public CompletionStage connect() { + + return client.query("SELECT 1").execute() + .map(mssqlRowSet -> { + assertEquals(1, mssqlRowSet.size()); + assertEquals(1, mssqlRowSet.iterator().next().getInteger(0)); + return "OK"; + }) + .subscribeAsCompletionStage(); + } + +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CustomCredentialsProvider.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CustomCredentialsProvider.java new file mode 100644 index 0000000000000..6d04f7c7a9b13 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/CustomCredentialsProvider.java @@ -0,0 +1,27 @@ +package io.quarkus.reactive.mssql.client; + +import java.util.HashMap; +import java.util.Map; + +import javax.enterprise.context.ApplicationScoped; + +import org.jboss.logging.Logger; + +import io.quarkus.arc.Unremovable; +import io.quarkus.credentials.CredentialsProvider; + +@ApplicationScoped +@Unremovable +public class CustomCredentialsProvider implements CredentialsProvider { + + private static final Logger log = Logger.getLogger(CustomCredentialsProvider.class.getName()); + + @Override + public Map getCredentials(String credentialsProviderName) { + Map properties = new HashMap<>(); + properties.put(USER_PROPERTY_NAME, "sa"); + properties.put(PASSWORD_PROPERTY_NAME, "A_Str0ng_Required_Password"); + log.info("credentials provider returning " + properties); + return properties; + } +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DevModeResource.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DevModeResource.java new file mode 100644 index 0000000000000..c7f93aa21e0bc --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DevModeResource.java @@ -0,0 +1,42 @@ +package io.quarkus.reactive.mssql.client; + +import java.net.ConnectException; +import java.sql.SQLException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import io.vertx.mssqlclient.MSSQLPool; + +@Path("/dev") +public class DevModeResource { + + @Inject + MSSQLPool client; + + @GET + @Path("/error") + @Produces(MediaType.TEXT_PLAIN) + public CompletionStage getErrorMessage() throws SQLException { + CompletableFuture future = new CompletableFuture<>(); + client.query("SELECT 1").execute(ar -> { + Class expectedExceptionClass = ConnectException.class; + if (ar.succeeded()) { + future.complete(Response.serverError().entity("Expected SQL query to fail").build()); + } else if (!expectedExceptionClass.isAssignableFrom(ar.cause().getClass())) { + ar.cause().printStackTrace(); + future.complete(Response.serverError() + .entity("Expected " + expectedExceptionClass + ", got " + ar.cause().getClass()).build()); + } else { + future.complete(Response.ok(ar.cause().getMessage()).build()); + } + }); + return future; + } +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/MSSQLPoolProducerTest.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/MSSQLPoolProducerTest.java new file mode 100644 index 0000000000000..01ee67f1871a1 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/MSSQLPoolProducerTest.java @@ -0,0 +1,66 @@ +package io.quarkus.reactive.mssql.client; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.mssqlclient.MSSQLPool; + +public class MSSQLPoolProducerTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withConfigurationResource("application-default-datasource.properties") + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(BeanUsingBareMSSQLClient.class) + .addClasses(BeanUsingMutinyMSSQLClient.class)); + + @Inject + BeanUsingBareMSSQLClient beanUsingBare; + + @Inject + BeanUsingMutinyMSSQLClient beanUsingMutiny; + + @Test + public void testVertxInjection() { + beanUsingBare.verify() + .thenCompose(v -> beanUsingMutiny.verify()) + .toCompletableFuture() + .join(); + } + + @ApplicationScoped + static class BeanUsingBareMSSQLClient { + + @Inject + MSSQLPool mssqlClient; + + public CompletionStage verify() { + CompletableFuture cf = new CompletableFuture<>(); + mssqlClient.query("SELECT 1").execute(ar -> cf.complete(null)); + return cf; + } + } + + @ApplicationScoped + static class BeanUsingMutinyMSSQLClient { + + @Inject + io.vertx.mutiny.mssqlclient.MSSQLPool mssqlClient; + + public CompletionStage verify() { + return mssqlClient.query("SELECT 1").execute() + .onItem().ignore().andContinueWithNull() + .onFailure().recoverWithItem((Void) null) + .subscribeAsCompletionStage(); + } + } +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/MultipleDataSourcesTest.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/MultipleDataSourcesTest.java new file mode 100644 index 0000000000000..59bdc47d14fc9 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/MultipleDataSourcesTest.java @@ -0,0 +1,79 @@ +package io.quarkus.reactive.mssql.client; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.reactive.datasource.ReactiveDataSource; +import io.quarkus.test.QuarkusUnitTest; +import io.vertx.mssqlclient.MSSQLPool; + +public class MultipleDataSourcesTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withConfigurationResource("application-multiple-datasources.properties") + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClasses(BeanUsingDefaultDataSource.class) + .addClass(BeanUsingHibernateDataSource.class)); + + @Inject + BeanUsingDefaultDataSource beanUsingDefaultDataSource; + + @Inject + BeanUsingHibernateDataSource beanUsingHibernateDataSource; + + @Test + public void testMultipleDataSources() { + beanUsingDefaultDataSource.verify() + .thenCompose(v -> beanUsingHibernateDataSource.verify()) + .toCompletableFuture() + .join(); + } + + @ApplicationScoped + static class BeanUsingDefaultDataSource { + + @Inject + MSSQLPool msSQLClient; + + public CompletionStage verify() { + CompletableFuture cf = new CompletableFuture<>(); + msSQLClient.query("SELECT 1").execute(ar -> { + if (ar.failed()) { + cf.completeExceptionally(ar.cause()); + } else { + cf.complete(null); + } + }); + return cf; + } + } + + @ApplicationScoped + static class BeanUsingHibernateDataSource { + + @Inject + @ReactiveDataSource("hibernate") + MSSQLPool msSQLClient; + + public CompletionStage verify() { + CompletableFuture cf = new CompletableFuture<>(); + msSQLClient.query("SELECT 1").execute(ar -> { + if (ar.failed()) { + cf.completeExceptionally(ar.cause()); + } else { + cf.complete(null); + } + }); + return cf; + } + } +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ReactiveMSSQLReloadTest.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ReactiveMSSQLReloadTest.java new file mode 100644 index 0000000000000..b930cc9b0d2ee --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/ReactiveMSSQLReloadTest.java @@ -0,0 +1,39 @@ +package io.quarkus.reactive.mssql.client; + +import org.hamcrest.Matchers; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusDevModeTest; +import io.restassured.RestAssured; + +public class ReactiveMSSQLReloadTest { + + @RegisterExtension + public static final QuarkusDevModeTest test = new QuarkusDevModeTest() + .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) + .addClass(DevModeResource.class) + .add(new StringAsset("quarkus.datasource.db-kind=mssql\n" + + "quarkus.datasource.reactive.url=vertx-reactive:sqlserver://localhost:3314/reload_test"), + "application.properties")); + + @Test + public void testHotReplacement() { + RestAssured + .get("/dev/error") + .then() + .statusCode(200) + .body(Matchers.endsWith(":3314")); + + test.modifyResourceFile("application.properties", s -> s.replace(":3314", ":9314")); + + RestAssured + .get("/dev/error") + .then() + .statusCode(200) + .body(Matchers.endsWith(":9314")); + } +} diff --git a/extensions/reactive-mssql-client/deployment/src/test/resources/application-credentials.properties b/extensions/reactive-mssql-client/deployment/src/test/resources/application-credentials.properties new file mode 100644 index 0000000000000..93bbbf079e3c7 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/resources/application-credentials.properties @@ -0,0 +1,3 @@ +quarkus.datasource.db-kind=mssql +quarkus.datasource.credentials-provider=custom +quarkus.datasource.reactive.url=${reactive-mssql.url} diff --git a/extensions/reactive-mssql-client/deployment/src/test/resources/application-default-datasource.properties b/extensions/reactive-mssql-client/deployment/src/test/resources/application-default-datasource.properties new file mode 100644 index 0000000000000..e5bebc689dee1 --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/resources/application-default-datasource.properties @@ -0,0 +1,2 @@ +quarkus.datasource.db-kind=mssql +quarkus.datasource.username=username-default diff --git a/extensions/reactive-mssql-client/deployment/src/test/resources/application-multiple-datasources.properties b/extensions/reactive-mssql-client/deployment/src/test/resources/application-multiple-datasources.properties new file mode 100644 index 0000000000000..fa3231dd52c3e --- /dev/null +++ b/extensions/reactive-mssql-client/deployment/src/test/resources/application-multiple-datasources.properties @@ -0,0 +1,9 @@ +quarkus.datasource.db-kind=mssql +quarkus.datasource.username=sa +quarkus.datasource.password=A_Str0ng_Required_Password +quarkus.datasource.reactive.url=${reactive-mssql.url} + +quarkus.datasource."hibernate".db-kind=mssql +quarkus.datasource."hibernate".username=sa +quarkus.datasource."hibernate".password=A_Str0ng_Required_Password +quarkus.datasource."hibernate".reactive.url=${reactive-mssql.url} \ No newline at end of file diff --git a/extensions/reactive-mssql-client/pom.xml b/extensions/reactive-mssql-client/pom.xml new file mode 100644 index 0000000000000..4dc267f914432 --- /dev/null +++ b/extensions/reactive-mssql-client/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + + quarkus-extensions-parent + io.quarkus + 999-SNAPSHOT + ../pom.xml + + + quarkus-reactive-mssql-client-parent + pom + + Quarkus - Reactive MS SQL Client + + + deployment + runtime + + + + diff --git a/extensions/reactive-mssql-client/runtime/pom.xml b/extensions/reactive-mssql-client/runtime/pom.xml new file mode 100644 index 0000000000000..beb4a5a46650b --- /dev/null +++ b/extensions/reactive-mssql-client/runtime/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + + io.quarkus + quarkus-reactive-mssql-client-parent + 999-SNAPSHOT + + + quarkus-reactive-mssql-client + + Quarkus - Reactive MS SQL Client - Runtime + Connect to the MS SQL database using the reactive pattern + + + io.quarkus + quarkus-reactive-datasource + + + io.quarkus + quarkus-vertx + + + io.vertx + vertx-mssql-client + + + io.smallrye.reactive + smallrye-mutiny-vertx-mssql-client + + + io.quarkus + quarkus-credentials + + + + io.quarkus + quarkus-smallrye-health + true + + + + + + + io.quarkus + quarkus-bootstrap-maven-plugin + + + maven-compiler-plugin + + + + io.quarkus + quarkus-extension-processor + ${project.version} + + + + + + + diff --git a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourceReactiveMSSQLConfig.java b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourceReactiveMSSQLConfig.java new file mode 100644 index 0000000000000..1cb2bbacc3df6 --- /dev/null +++ b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourceReactiveMSSQLConfig.java @@ -0,0 +1,8 @@ +package io.quarkus.reactive.mssql.client.runtime; + +import io.quarkus.runtime.annotations.ConfigGroup; + +@ConfigGroup +public class DataSourceReactiveMSSQLConfig { + +} diff --git a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourcesReactiveMSSQLConfig.java b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourcesReactiveMSSQLConfig.java new file mode 100644 index 0000000000000..3b40b2d3d76e7 --- /dev/null +++ b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourcesReactiveMSSQLConfig.java @@ -0,0 +1,62 @@ +package io.quarkus.reactive.mssql.client.runtime; + +import java.util.Map; + +import io.quarkus.datasource.common.runtime.DataSourceUtil; +import io.quarkus.runtime.annotations.ConfigDocMapKey; +import io.quarkus.runtime.annotations.ConfigDocSection; +import io.quarkus.runtime.annotations.ConfigGroup; +import io.quarkus.runtime.annotations.ConfigItem; +import io.quarkus.runtime.annotations.ConfigPhase; +import io.quarkus.runtime.annotations.ConfigRoot; + +@ConfigRoot(name = "datasource", phase = ConfigPhase.RUN_TIME) +public class DataSourcesReactiveMSSQLConfig { + + /** + * The default datasource. + */ + @ConfigItem(name = "reactive.mssql") + public DataSourceReactiveMSSQLConfig defaultDataSource; + + /** + * Additional named datasources. + */ + @ConfigDocSection + @ConfigDocMapKey("datasource-name") + @ConfigItem(name = ConfigItem.PARENT) + public Map namedDataSources; + + public DataSourceReactiveMSSQLConfig getDataSourceReactiveRuntimeConfig(String dataSourceName) { + if (DataSourceUtil.isDefault(dataSourceName)) { + return defaultDataSource; + } + + DataSourceReactiveMSSQLOuterNamedConfig dataSourceReactiveMSSQLOuterNamedConfig = namedDataSources + .get(dataSourceName); + if (dataSourceReactiveMSSQLOuterNamedConfig == null) { + return new DataSourceReactiveMSSQLConfig(); + } + + return dataSourceReactiveMSSQLOuterNamedConfig.reactive.mssql; + } + + @ConfigGroup + public static class DataSourceReactiveMSSQLOuterNamedConfig { + + /** + * The MSSQL-specific configuration. + */ + public DataSourceReactiveMSSQLOuterNestedNamedConfig reactive; + } + + @ConfigGroup + public static class DataSourceReactiveMSSQLOuterNestedNamedConfig { + + /** + * The MSSQL-specific configuration. + */ + public DataSourceReactiveMSSQLConfig mssql; + } + +} diff --git a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java new file mode 100644 index 0000000000000..bda6c4f5f3169 --- /dev/null +++ b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java @@ -0,0 +1,134 @@ +package io.quarkus.reactive.mssql.client.runtime; + +import static io.quarkus.credentials.CredentialsProvider.PASSWORD_PROPERTY_NAME; +import static io.quarkus.credentials.CredentialsProvider.USER_PROPERTY_NAME; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.jboss.logging.Logger; + +import io.quarkus.credentials.CredentialsProvider; +import io.quarkus.credentials.runtime.CredentialsProviderFinder; +import io.quarkus.datasource.runtime.DataSourceRuntimeConfig; +import io.quarkus.datasource.runtime.DataSourcesRuntimeConfig; +import io.quarkus.reactive.datasource.runtime.DataSourceReactiveRuntimeConfig; +import io.quarkus.reactive.datasource.runtime.DataSourcesReactiveRuntimeConfig; +import io.quarkus.runtime.RuntimeValue; +import io.quarkus.runtime.ShutdownContext; +import io.quarkus.runtime.annotations.Recorder; +import io.vertx.core.Vertx; +import io.vertx.mssqlclient.MSSQLConnectOptions; +import io.vertx.mssqlclient.MSSQLPool; +import io.vertx.sqlclient.PoolOptions; + +@SuppressWarnings("deprecation") +@Recorder +public class MSSQLPoolRecorder { + + private static final Logger log = Logger.getLogger(MSSQLPoolRecorder.class); + + public RuntimeValue configureMSSQLPool(RuntimeValue vertx, + String dataSourceName, + DataSourcesRuntimeConfig dataSourcesRuntimeConfig, + DataSourcesReactiveRuntimeConfig dataSourcesReactiveRuntimeConfig, + DataSourcesReactiveMSSQLConfig dataSourcesReactiveMSSQLConfig, + ShutdownContext shutdown) { + + MSSQLPool mssqlPool = initialize(vertx.getValue(), + dataSourcesRuntimeConfig.getDataSourceRuntimeConfig(dataSourceName), + dataSourcesReactiveRuntimeConfig.getDataSourceReactiveRuntimeConfig(dataSourceName), + dataSourcesReactiveMSSQLConfig.getDataSourceReactiveRuntimeConfig(dataSourceName)); + + shutdown.addShutdownTask(mssqlPool::close); + return new RuntimeValue<>(mssqlPool); + } + + public RuntimeValue mutinyMSSQLPool(RuntimeValue mssqlPool) { + return new RuntimeValue<>(io.vertx.mutiny.mssqlclient.MSSQLPool.newInstance(mssqlPool.getValue())); + } + + private MSSQLPool initialize(Vertx vertx, DataSourceRuntimeConfig dataSourceRuntimeConfig, + DataSourceReactiveRuntimeConfig dataSourceReactiveRuntimeConfig, + DataSourceReactiveMSSQLConfig dataSourceReactiveMSSQLConfig) { + PoolOptions poolOptions = toPoolOptions(dataSourceRuntimeConfig, dataSourceReactiveRuntimeConfig, + dataSourceReactiveMSSQLConfig); + MSSQLConnectOptions mssqlConnectOptions = toMSSQLConnectOptions(dataSourceRuntimeConfig, + dataSourceReactiveRuntimeConfig, dataSourceReactiveMSSQLConfig); + if (dataSourceReactiveRuntimeConfig.threadLocal.isPresent()) { + log.warn( + "Configuration element 'thread-local' on Reactive datasource connections is deprecated and will be ignored. The started pool will always be based on a per-thread separate pool now."); + } + return MSSQLPool.pool(vertx, mssqlConnectOptions, poolOptions); + } + + private PoolOptions toPoolOptions(DataSourceRuntimeConfig dataSourceRuntimeConfig, + DataSourceReactiveRuntimeConfig dataSourceReactiveRuntimeConfig, + DataSourceReactiveMSSQLConfig dataSourceReactiveMSSQLConfig) { + PoolOptions poolOptions; + poolOptions = new PoolOptions(); + + if (dataSourceReactiveRuntimeConfig.maxSize.isPresent()) { + poolOptions.setMaxSize(dataSourceReactiveRuntimeConfig.maxSize.getAsInt()); + } + + if (dataSourceReactiveRuntimeConfig.idleTimeout.isPresent()) { + int idleTimeout = Math.toIntExact(dataSourceReactiveRuntimeConfig.idleTimeout.get().toMillis()); + poolOptions.setIdleTimeout(idleTimeout).setIdleTimeoutUnit(TimeUnit.MILLISECONDS); + } + + return poolOptions; + } + + private MSSQLConnectOptions toMSSQLConnectOptions(DataSourceRuntimeConfig dataSourceRuntimeConfig, + DataSourceReactiveRuntimeConfig dataSourceReactiveRuntimeConfig, + DataSourceReactiveMSSQLConfig dataSourceReactiveMSSQLConfig) { + MSSQLConnectOptions mssqlConnectOptions; + if (dataSourceReactiveRuntimeConfig.url.isPresent()) { + String url = dataSourceReactiveRuntimeConfig.url.get(); + // clean up the URL to make migrations easier + if (url.startsWith("vertx-reactive:sqlserver://")) { + url = url.substring("vertx-reactive:".length()); + } + mssqlConnectOptions = MSSQLConnectOptions.fromUri(url); + } else { + mssqlConnectOptions = new MSSQLConnectOptions(); + } + + if (dataSourceRuntimeConfig.username.isPresent()) { + mssqlConnectOptions.setUser(dataSourceRuntimeConfig.username.get()); + } + + if (dataSourceRuntimeConfig.password.isPresent()) { + mssqlConnectOptions.setPassword(dataSourceRuntimeConfig.password.get()); + } + + // credentials provider + if (dataSourceRuntimeConfig.credentialsProvider.isPresent()) { + String beanName = dataSourceRuntimeConfig.credentialsProviderName.orElse(null); + CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName); + String name = dataSourceRuntimeConfig.credentialsProvider.get(); + Map credentials = credentialsProvider.getCredentials(name); + String user = credentials.get(USER_PROPERTY_NAME); + String password = credentials.get(PASSWORD_PROPERTY_NAME); + if (user != null) { + mssqlConnectOptions.setUser(user); + } + if (password != null) { + mssqlConnectOptions.setPassword(password); + } + } + + mssqlConnectOptions.setReconnectAttempts(dataSourceReactiveRuntimeConfig.reconnectAttempts); + + mssqlConnectOptions.setReconnectInterval(dataSourceReactiveRuntimeConfig.reconnectInterval.toMillis()); + + if (dataSourceReactiveRuntimeConfig.hostnameVerificationAlgorithm.isPresent()) { + mssqlConnectOptions.setHostnameVerificationAlgorithm( + dataSourceReactiveRuntimeConfig.hostnameVerificationAlgorithm.get()); + } + + return mssqlConnectOptions; + } + +} diff --git a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/health/ReactiveMSSQLDataSourcesHealthCheck.java b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/health/ReactiveMSSQLDataSourcesHealthCheck.java new file mode 100644 index 0000000000000..15420bfe61c47 --- /dev/null +++ b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/health/ReactiveMSSQLDataSourcesHealthCheck.java @@ -0,0 +1,29 @@ +package io.quarkus.reactive.mssql.client.runtime.health; + +import javax.annotation.PostConstruct; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Any; + +import org.eclipse.microprofile.health.Readiness; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.InstanceHandle; +import io.quarkus.reactive.datasource.runtime.ReactiveDatasourceHealthCheck; +import io.vertx.mssqlclient.MSSQLPool; + +@Readiness +@ApplicationScoped +class ReactiveMSSQLDataSourcesHealthCheck extends ReactiveDatasourceHealthCheck { + + public ReactiveMSSQLDataSourcesHealthCheck() { + super("Reactive MS SQL connections health check", "SELECT 1"); + } + + @PostConstruct + protected void init() { + for (InstanceHandle handle : Arc.container().select(MSSQLPool.class, Any.Literal.INSTANCE).handles()) { + addPool(getPoolName(handle.getBean()), handle.get()); + } + } + +} diff --git a/extensions/reactive-mssql-client/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/reactive-mssql-client/runtime/src/main/resources/META-INF/quarkus-extension.yaml new file mode 100644 index 0000000000000..042cfecc7dce6 --- /dev/null +++ b/extensions/reactive-mssql-client/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -0,0 +1,17 @@ +--- +artifact: ${project.groupId}:${project.artifactId}:${project.version} +name: "Reactive MS SQL client" +metadata: + keywords: + - "eclipse-vert.x" + - "vertx" + - "vert.x" + - "reactive" + - "database" + - "data" + - "mssql" + guide: "https://quarkus.io/guides/reactive-sql-clients" + categories: + - "data" + - "reactive" + status: "preview" \ No newline at end of file diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 086e7db5e0aa6..978a312b4e3dc 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -100,6 +100,7 @@ reactive-db2-client reactive-pg-client reactive-mysql-client + reactive-mssql-client amazon-services test-extension amazon-lambda diff --git a/integration-tests/reactive-mssql-client/README.md b/integration-tests/reactive-mssql-client/README.md new file mode 100644 index 0000000000000..f514d58027388 --- /dev/null +++ b/integration-tests/reactive-mssql-client/README.md @@ -0,0 +1,28 @@ +# Reactive MS SQL example + +## Running the tests + +By default, the tests of this module are disabled. + +To run the tests in a standard JVM with MS SQL started as a Docker container, you can run the following command: + +``` +mvn clean install -Dtest-containers -Dstart-containers +``` + +Additionally, you can generate a native image and run the tests for this native image by adding `-Dnative`: + +``` +mvn clean install -Dtest-containers -Dstart-containers -Dnative +``` + +If you don't want to run MS SQL as a Docker container, you can start your own. +It needs to listen on the default port and be accessible to the user `sa` with the password `A_Str0ng_Required_Password`. + +You can then run the tests as follows (either with `-Dnative` or not): + +``` +mvn clean install -Dtest-containers +``` + +If you have specific requirements, you can define a specific connection URL with `-Dreactive-mssql.url=vertx-reactive:sqlserver://localhost:1433`. diff --git a/integration-tests/reactive-mssql-client/pom.xml b/integration-tests/reactive-mssql-client/pom.xml new file mode 100644 index 0000000000000..492561d14e520 --- /dev/null +++ b/integration-tests/reactive-mssql-client/pom.xml @@ -0,0 +1,239 @@ + + + 4.0.0 + + + io.quarkus + quarkus-integration-tests-parent + 999-SNAPSHOT + + + quarkus-integration-test-reactive-mssql-client + + Quarkus - Integration Tests - Reactive MS SQL Client + + + vertx-reactive:sqlserver://localhost:1433 + mcr.microsoft.com/mssql/server:2019-latest + + + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-reactive-mssql-client + + + io.quarkus + quarkus-smallrye-health + + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + io.quarkus + quarkus-reactive-mssql-client-deployment + ${project.version} + pom + test + + + * + * + + + + + io.quarkus + quarkus-resteasy-deployment + ${project.version} + pom + test + + + * + * + + + + + io.quarkus + quarkus-smallrye-health-deployment + ${project.version} + pom + test + + + * + * + + + + + + + + + src/main/resources + true + + + + + maven-surefire-plugin + + true + + + + maven-failsafe-plugin + + true + + + + io.quarkus + quarkus-maven-plugin + + + + build + + + + + + + + + + test-mssql + + + test-containers + + + + + + maven-surefire-plugin + + false + + + + maven-failsafe-plugin + + false + + + + + + + docker-mssql + + + start-containers + + + + vertx-reactive:sqlserver://localhost:1435 + + + + + io.fabric8 + docker-maven-plugin + + + + ${mssql.image} + quarkus-test-mssql + + + bridge + + + 1435:1433 + + + Y + A_Str0ng_Required_Password + + + MSSQL: + default + cyan + + + + + direct + + 1433 + + + + + + + + true + + + + docker-start + compile + + stop + start + + + + docker-stop + post-integration-test + + stop + + + + + + org.codehaus.mojo + exec-maven-plugin + + + docker-prune + generate-resources + + exec + + + ${docker-prune.location} + + + + + + + + + + diff --git a/integration-tests/reactive-mssql-client/src/main/java/io/quarkus/it/reactive/mssql/client/FruitResource.java b/integration-tests/reactive-mssql-client/src/main/java/io/quarkus/it/reactive/mssql/client/FruitResource.java new file mode 100644 index 0000000000000..6284cf1d78656 --- /dev/null +++ b/integration-tests/reactive-mssql-client/src/main/java/io/quarkus/it/reactive/mssql/client/FruitResource.java @@ -0,0 +1,51 @@ +package io.quarkus.it.reactive.mssql.client; + +import java.util.concurrent.CompletionStage; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; +import io.vertx.mutiny.mssqlclient.MSSQLPool; +import io.vertx.mutiny.sqlclient.Row; + +@Path("/fruits") +public class FruitResource { + + @Inject + MSSQLPool client; + + @PostConstruct + void setupDb() { + client.query("DROP TABLE IF EXISTS fruits").execute() + .flatMap(r -> client.query("CREATE TABLE fruits (id BIGINT IDENTITY PRIMARY KEY, name VARCHAR(500) NOT NULL)") + .execute()) + .flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Orange')").execute()) + .flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Pear')").execute()) + .flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Apple')").execute()) + .await().indefinitely(); + } + + @GET + public CompletionStage listFruits() { + return client.query("SELECT * FROM fruits").execute() + .map(pgRowSet -> { + JsonArray jsonArray = new JsonArray(); + for (Row row : pgRowSet) { + jsonArray.add(toJson(row)); + } + return jsonArray; + }) + .subscribeAsCompletionStage(); + } + + private JsonObject toJson(Row row) { + return new JsonObject() + .put("id", row.getLong("id")) + .put("name", row.getString("name")); + } + +} diff --git a/integration-tests/reactive-mssql-client/src/main/resources/application.properties b/integration-tests/reactive-mssql-client/src/main/resources/application.properties new file mode 100644 index 0000000000000..0ff550c1f8b67 --- /dev/null +++ b/integration-tests/reactive-mssql-client/src/main/resources/application.properties @@ -0,0 +1,4 @@ +quarkus.datasource.db-kind=mssql +quarkus.datasource.username=sa +quarkus.datasource.password=A_Str0ng_Required_Password +quarkus.datasource.reactive.url=${reactive-mssql.url} diff --git a/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/FruitsEndpointTest.java b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/FruitsEndpointTest.java new file mode 100644 index 0000000000000..8c91bc477e4b2 --- /dev/null +++ b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/FruitsEndpointTest.java @@ -0,0 +1,25 @@ +package io.quarkus.it.reactive.mssql.client; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.containsString; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class FruitsEndpointTest { + + @Test + public void testListAllFruits() { + given() + .when().get("/fruits") + .then() + .statusCode(200) + .body( + containsString("Orange"), + containsString("Pear"), + containsString("Apple")); + } + +} diff --git a/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HealthCheckIT.java b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HealthCheckIT.java new file mode 100644 index 0000000000000..07b3497444502 --- /dev/null +++ b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HealthCheckIT.java @@ -0,0 +1,7 @@ +package io.quarkus.it.reactive.mssql.client; + +import io.quarkus.test.junit.NativeImageTest; + +@NativeImageTest +public class HealthCheckIT extends HealthCheckTest { +} diff --git a/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HealthCheckTest.java b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HealthCheckTest.java new file mode 100644 index 0000000000000..37862cdd496b6 --- /dev/null +++ b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HealthCheckTest.java @@ -0,0 +1,24 @@ +package io.quarkus.it.reactive.mssql.client; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.containsInAnyOrder; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; + +@QuarkusTest +public class HealthCheckTest { + @Test + public void testHealthCheck() { + RestAssured.when().get("/q/health").then() + .contentType(ContentType.JSON) + .header("Content-Type", containsString("charset=UTF-8")) + .body("status", is("UP"), + "checks.status", containsInAnyOrder("UP"), + "checks.name", containsInAnyOrder("Reactive MS SQL connections health check")); + } +} diff --git a/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HotReloadFruitResource.java b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HotReloadFruitResource.java new file mode 100644 index 0000000000000..f78a572737ae2 --- /dev/null +++ b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/HotReloadFruitResource.java @@ -0,0 +1,51 @@ +package io.quarkus.it.reactive.mssql.client; + +import java.util.concurrent.CompletionStage; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; +import io.vertx.mutiny.mssqlclient.MSSQLPool; +import io.vertx.mutiny.sqlclient.Row; + +@Path("/hot-fruits") +public class HotReloadFruitResource { + + @Inject + MSSQLPool client; + + @PostConstruct + void setupDb() { + client.query("DROP TABLE IF EXISTS fruits").execute() + .flatMap(r -> client.query("CREATE TABLE fruits (id BIGINT IDENTITY PRIMARY KEY, name VARCHAR(500) NOT NULL)") + .execute()) + .flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Orange')").execute()) + .flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Pear')").execute()) + .flatMap(r -> client.query("INSERT INTO fruits (name) VALUES ('Apple')").execute()) + .await().indefinitely(); + } + + @GET + public CompletionStage listFruits() { + return client.query("SELECT * FROM fruits").execute() + .map(pgRowSet -> { + JsonArray jsonArray = new JsonArray(); + for (Row row : pgRowSet) { + jsonArray.add(toJson(row)); + } + return jsonArray; + }) + .subscribeAsCompletionStage(); + } + + private JsonObject toJson(Row row) { + return new JsonObject() + .put("id", row.getLong("id")) + .put("name", row.getString("name")); + } + +} diff --git a/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/NativeFruitsEndpointIT.java b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/NativeFruitsEndpointIT.java new file mode 100644 index 0000000000000..08efce2f0a26d --- /dev/null +++ b/integration-tests/reactive-mssql-client/src/test/java/io/quarkus/it/reactive/mssql/client/NativeFruitsEndpointIT.java @@ -0,0 +1,10 @@ +package io.quarkus.it.reactive.mssql.client; + +import io.quarkus.test.junit.NativeImageTest; + +@NativeImageTest +public class NativeFruitsEndpointIT extends FruitsEndpointTest { + + // Runs the same tests as the parent class + +} diff --git a/integration-tests/reactive-mssql-client/src/test/resources/application-tl.properties b/integration-tests/reactive-mssql-client/src/test/resources/application-tl.properties new file mode 100644 index 0000000000000..7c97b5798fde4 --- /dev/null +++ b/integration-tests/reactive-mssql-client/src/test/resources/application-tl.properties @@ -0,0 +1,5 @@ +quarkus.datasource.db-kind=mssql +quarkus.datasource.username=sa +quarkus.datasource.password=A_Str0ng_Required_Password +quarkus.datasource.reactive.url=${reactive-mssql.url} +quarkus.log.category."io.quarkus.reactive.datasource".level=DEBUG From 65ed225ce53de3baee8bf69b6efa4a7dd346c37d Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Thu, 1 Jul 2021 17:45:10 +0200 Subject: [PATCH 2/7] Updates after running update-extension-dependencies.sh --- devtools/bom-descriptor-json/pom.xml | 4 ++-- docs/pom.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/devtools/bom-descriptor-json/pom.xml b/devtools/bom-descriptor-json/pom.xml index bea45061dfdaf..d0ad2a17f2444 100644 --- a/devtools/bom-descriptor-json/pom.xml +++ b/devtools/bom-descriptor-json/pom.xml @@ -1802,7 +1802,7 @@ io.quarkus - quarkus-reactive-mysql-client + quarkus-reactive-mssql-client ${project.version} pom test @@ -1815,7 +1815,7 @@ io.quarkus - quarkus-reactive-mssql-client + quarkus-reactive-mysql-client ${project.version} pom test diff --git a/docs/pom.xml b/docs/pom.xml index cfdd6b7c677fb..3782c7fec1570 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -1763,7 +1763,7 @@ io.quarkus - quarkus-reactive-mysql-client-deployment + quarkus-reactive-mssql-client-deployment ${project.version} pom test @@ -1776,7 +1776,7 @@ io.quarkus - quarkus-reactive-mssql-client-deployment + quarkus-reactive-mysql-client-deployment ${project.version} pom test From f8b8c28e1a22350580d956376741be72804c6b0d Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Fri, 2 Jul 2021 16:45:57 +0200 Subject: [PATCH 3/7] Expand Microsoft SQL Server name --- docs/src/main/asciidoc/datasource.adoc | 2 +- extensions/reactive-mssql-client/deployment/pom.xml | 2 +- extensions/reactive-mssql-client/runtime/pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/main/asciidoc/datasource.adoc b/docs/src/main/asciidoc/datasource.adoc index 0ed28de56feed..3e9e062b788e4 100644 --- a/docs/src/main/asciidoc/datasource.adoc +++ b/docs/src/main/asciidoc/datasource.adoc @@ -662,7 +662,7 @@ include::{generated-dir}/config/quarkus-reactive-db2-client.adoc[opts=optional, include::{generated-dir}/config/quarkus-reactive-mysql-client.adoc[opts=optional, leveloffset=+1] -=== Reactive MS SQL Specific Configuration +=== Reactive Microsoft SQL Server Specific Configuration include::{generated-dir}/config/quarkus-reactive-mssql-client.adoc[opts=optional, leveloffset=+1] diff --git a/extensions/reactive-mssql-client/deployment/pom.xml b/extensions/reactive-mssql-client/deployment/pom.xml index 278a3d9dc9898..96035897b9203 100644 --- a/extensions/reactive-mssql-client/deployment/pom.xml +++ b/extensions/reactive-mssql-client/deployment/pom.xml @@ -12,7 +12,7 @@ quarkus-reactive-mssql-client-deployment - Quarkus - Reactive MS SQL Client - Deployment + Quarkus - Reactive Microsoft SQL Server Client - Deployment vertx-reactive:sqlserver://localhost:1433 diff --git a/extensions/reactive-mssql-client/runtime/pom.xml b/extensions/reactive-mssql-client/runtime/pom.xml index beb4a5a46650b..38033f34ccbb7 100644 --- a/extensions/reactive-mssql-client/runtime/pom.xml +++ b/extensions/reactive-mssql-client/runtime/pom.xml @@ -12,8 +12,8 @@ quarkus-reactive-mssql-client - Quarkus - Reactive MS SQL Client - Runtime - Connect to the MS SQL database using the reactive pattern + Quarkus - Reactive Microsoft SQL Server Client - Runtime + Connect to the Microsoft SQL Server database using the reactive pattern io.quarkus From d1759c0a1f0be44a645b5a41b22566d704c713cd Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Fri, 2 Jul 2021 16:46:29 +0200 Subject: [PATCH 4/7] Remove redundant stacktrace from the test console --- .../java/io/quarkus/reactive/mssql/client/DevModeResource.java | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DevModeResource.java b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DevModeResource.java index c7f93aa21e0bc..32de811a4c67c 100644 --- a/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DevModeResource.java +++ b/extensions/reactive-mssql-client/deployment/src/test/java/io/quarkus/reactive/mssql/client/DevModeResource.java @@ -30,7 +30,6 @@ public CompletionStage getErrorMessage() throws SQLException { if (ar.succeeded()) { future.complete(Response.serverError().entity("Expected SQL query to fail").build()); } else if (!expectedExceptionClass.isAssignableFrom(ar.cause().getClass())) { - ar.cause().printStackTrace(); future.complete(Response.serverError() .entity("Expected " + expectedExceptionClass + ", got " + ar.cause().getClass()).build()); } else { From 614db32231426f65f70ab566549b3bcda51e0da7 Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Fri, 2 Jul 2021 16:50:32 +0200 Subject: [PATCH 5/7] MSSQL Reactive Client SSL not supported yet --- .../reactive/mssql/client/runtime/MSSQLPoolRecorder.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java index bda6c4f5f3169..89e93d99951ae 100644 --- a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java +++ b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java @@ -122,12 +122,6 @@ private MSSQLConnectOptions toMSSQLConnectOptions(DataSourceRuntimeConfig dataSo mssqlConnectOptions.setReconnectAttempts(dataSourceReactiveRuntimeConfig.reconnectAttempts); mssqlConnectOptions.setReconnectInterval(dataSourceReactiveRuntimeConfig.reconnectInterval.toMillis()); - - if (dataSourceReactiveRuntimeConfig.hostnameVerificationAlgorithm.isPresent()) { - mssqlConnectOptions.setHostnameVerificationAlgorithm( - dataSourceReactiveRuntimeConfig.hostnameVerificationAlgorithm.get()); - } - return mssqlConnectOptions; } From 40baa0d05e14c96f6f50178d172c404848c7cba8 Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Fri, 2 Jul 2021 16:57:26 +0200 Subject: [PATCH 6/7] TDS Packet size configurable with Vert.x 4.1.1 --- .../client/runtime/DataSourceReactiveMSSQLConfig.java | 9 +++++++++ .../reactive/mssql/client/runtime/MSSQLPoolRecorder.java | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourceReactiveMSSQLConfig.java b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourceReactiveMSSQLConfig.java index 1cb2bbacc3df6..90ede4693916b 100644 --- a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourceReactiveMSSQLConfig.java +++ b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/DataSourceReactiveMSSQLConfig.java @@ -1,8 +1,17 @@ package io.quarkus.reactive.mssql.client.runtime; +import java.util.OptionalInt; + import io.quarkus.runtime.annotations.ConfigGroup; +import io.quarkus.runtime.annotations.ConfigItem; @ConfigGroup public class DataSourceReactiveMSSQLConfig { + /** + * The desired size (in bytes) for TDS packets. + */ + @ConfigItem + public OptionalInt packetSize = OptionalInt.empty(); + } diff --git a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java index 89e93d99951ae..ffcd777a40b39 100644 --- a/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java +++ b/extensions/reactive-mssql-client/runtime/src/main/java/io/quarkus/reactive/mssql/client/runtime/MSSQLPoolRecorder.java @@ -95,6 +95,10 @@ private MSSQLConnectOptions toMSSQLConnectOptions(DataSourceRuntimeConfig dataSo mssqlConnectOptions = new MSSQLConnectOptions(); } + if (dataSourceReactiveMSSQLConfig.packetSize.isPresent()) { + mssqlConnectOptions.setPacketSize(dataSourceReactiveMSSQLConfig.packetSize.getAsInt()); + } + if (dataSourceRuntimeConfig.username.isPresent()) { mssqlConnectOptions.setUser(dataSourceRuntimeConfig.username.get()); } From c2d0747fed04388bf63e4676f85933e5b46d9815 Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Mon, 5 Jul 2021 16:06:48 +0200 Subject: [PATCH 7/7] Update MSSQL container setup to avoid timeouts Took example from JPA-MSSQL integration tests module. --- .../reactive-mssql-client/deployment/pom.xml | 15 ++++----------- integration-tests/reactive-mssql-client/pom.xml | 15 ++++----------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/extensions/reactive-mssql-client/deployment/pom.xml b/extensions/reactive-mssql-client/deployment/pom.xml index 96035897b9203..f7e90871b3ee5 100644 --- a/extensions/reactive-mssql-client/deployment/pom.xml +++ b/extensions/reactive-mssql-client/deployment/pom.xml @@ -16,7 +16,7 @@ vertx-reactive:sqlserver://localhost:1433 - mcr.microsoft.com/mssql/server:2019-latest + mcr.microsoft.com/mssql/server:2019-CU8-ubuntu-16.04 @@ -127,9 +127,6 @@ ${mssql.image} quarkus-test-mssql - - bridge - 1435:1433 @@ -143,13 +140,9 @@ cyan - - - direct - - 1433 - - + SQL Server is now ready for client connections + + diff --git a/integration-tests/reactive-mssql-client/pom.xml b/integration-tests/reactive-mssql-client/pom.xml index 492561d14e520..372d0c1758bd1 100644 --- a/integration-tests/reactive-mssql-client/pom.xml +++ b/integration-tests/reactive-mssql-client/pom.xml @@ -16,7 +16,7 @@ vertx-reactive:sqlserver://localhost:1433 - mcr.microsoft.com/mssql/server:2019-latest + mcr.microsoft.com/mssql/server:2019-CU8-ubuntu-16.04 @@ -166,9 +166,6 @@ ${mssql.image} quarkus-test-mssql - - bridge - 1435:1433 @@ -182,13 +179,9 @@ cyan - - - direct - - 1433 - - + SQL Server is now ready for client connections + +