From 0093e7cbc8d1c5d7983b54707665470ed2ec5127 Mon Sep 17 00:00:00 2001 From: Alex Katlein Date: Thu, 8 Feb 2024 19:05:54 +0100 Subject: [PATCH] Making sure deployment modules excluded in POM files aren't pulled in by the Gradle plugin This makes sure that exclusions in POM files of deployment modules are respects. Once case where this is critical is when using quarkus-hibernate-reactive. Its deployment module takes care of pulling in quarkus-hibernate-orm-deployment where it excludes Agroal and Narayana. If that exclusion isn't taken into account by the Gradle plugin, it pulls in quarkus-hibernate-orm-deployment on its own, where those other modules aren't excluded, which leads to a failure at runtime because Agroal tries to initialize and looks for a JDBC driver which isn't typically available in reactive DB scenarios. Fixes #38533 --- .../DeploymentClasspathBuilder.java | 9 +- devtools/gradle/gradle-model/build.gradle.kts | 3 + ...ApplicationDeploymentClasspathBuilder.java | 26 +- .../tooling/dependency/DependencyUtils.java | 30 +- .../quarkus/gradle/tooling/pom/PomUtils.java | 69 +++++ devtools/gradle/gradle/libs.versions.toml | 8 +- .../build.gradle | 32 ++ .../gradle.properties | 2 + .../settings.gradle | 17 ++ .../main/java/org/acme/GreetingResource.java | 16 + .../src/main/java/org/acme/MyEntity.java | 14 + .../resources/META-INF/resources/index.html | 285 ++++++++++++++++++ .../src/main/resources/application.properties | 5 + .../java/org/acme/GreetingResourceIT.java | 8 + .../java/org/acme/GreetingResourceTest.java | 21 ++ ...usionInExtensionDependencyDevModeTest.java | 27 ++ 16 files changed, 561 insertions(+), 11 deletions(-) create mode 100644 devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/pom/PomUtils.java create mode 100644 integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/gradle.properties create mode 100644 integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/settings.gradle create mode 100644 integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/java/org/acme/GreetingResource.java create mode 100644 integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/java/org/acme/MyEntity.java create mode 100644 integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/resources/META-INF/resources/index.html create mode 100644 integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/resources/application.properties create mode 100644 integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/native-test/java/org/acme/GreetingResourceIT.java create mode 100644 integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/test/java/org/acme/GreetingResourceTest.java create mode 100644 integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/MavenExclusionInExtensionDependencyDevModeTest.java diff --git a/devtools/gradle/gradle-extension-plugin/src/main/java/io/quarkus/extension/gradle/dependency/DeploymentClasspathBuilder.java b/devtools/gradle/gradle-extension-plugin/src/main/java/io/quarkus/extension/gradle/dependency/DeploymentClasspathBuilder.java index f7fef45daf6643..4a04c99a2edc04 100644 --- a/devtools/gradle/gradle-extension-plugin/src/main/java/io/quarkus/extension/gradle/dependency/DeploymentClasspathBuilder.java +++ b/devtools/gradle/gradle-extension-plugin/src/main/java/io/quarkus/extension/gradle/dependency/DeploymentClasspathBuilder.java @@ -33,6 +33,8 @@ public void exportDeploymentClasspath(String configurationName) { project.getConfigurations().getByName(configurationName)); Set> extensionDependencies = collectFirstMetQuarkusExtensions(configuration); + final Set seenDeploymentDependencies = new HashSet<>(); + DependencyHandler dependencies = project.getDependencies(); for (ExtensionDependency extension : extensionDependencies) { @@ -40,8 +42,13 @@ public void exportDeploymentClasspath(String configurationName) { continue; } + if (!seenDeploymentDependencies.add(DependencyUtils.getDeploymentDependencyIdentifier(extension))) { + continue; + } + dependencies.add(deploymentConfigurationName, - DependencyUtils.createDeploymentDependency(dependencies, extension)); + DependencyUtils.createDeploymentDependency(project, dependencies, extension, + seenDeploymentDependencies)); } }); } diff --git a/devtools/gradle/gradle-model/build.gradle.kts b/devtools/gradle/gradle-model/build.gradle.kts index be5055edd3d8c4..be24cf675335dc 100644 --- a/devtools/gradle/gradle-model/build.gradle.kts +++ b/devtools/gradle/gradle-model/build.gradle.kts @@ -3,7 +3,10 @@ plugins { } dependencies { + implementation(libs.maven.model) + compileOnly(libs.kotlin.gradle.plugin.api) + gradleApi() } group = "io.quarkus" diff --git a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/ApplicationDeploymentClasspathBuilder.java b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/ApplicationDeploymentClasspathBuilder.java index f3cd59c9d8f65d..1e3a53544995e6 100644 --- a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/ApplicationDeploymentClasspathBuilder.java +++ b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/ApplicationDeploymentClasspathBuilder.java @@ -205,8 +205,16 @@ private void setUpDeploymentConfiguration() { ConditionalDependenciesEnabler cdEnabler = new ConditionalDependenciesEnabler(project, mode, enforcedPlatforms); final Collection> allExtensions = cdEnabler.getAllExtensions(); - Set> extensions = collectFirstMetQuarkusExtensions(getRawRuntimeConfiguration(), - allExtensions); + + // linked hash set is very important here! we need to keep the first met dependencies + // at the start of the collection so dependency based exclusions stick! + // Example: this prevents pulling in hibernate-orm-deployment here if it has already been + // pulled in by hibernate-reactive where it excludes Agroal and Narayana. + // otherwise those get pulled in as well and lead to failures when trying to run + // an application with reactive DB drivers without JDBC drivers on the class path + Set> extensions = new LinkedHashSet<>( + collectFirstMetQuarkusExtensions(getRawRuntimeConfiguration(), + allExtensions)); // Add conditional extensions for (ExtensionDependency knownExtension : allExtensions) { if (knownExtension.isConditional()) { @@ -214,17 +222,29 @@ private void setUpDeploymentConfiguration() { } } + final Set seenDeploymentDependencies = new HashSet<>(); + final Set alreadyProcessed = new HashSet<>(extensions.size()); final DependencyHandler dependencies = project.getDependencies(); final Set deploymentDependencies = new HashSet<>(); + for (ExtensionDependency extension : extensions) { if (!alreadyProcessed.add(extension.getExtensionId())) { continue; } + if (!seenDeploymentDependencies.add(DependencyUtils.getDeploymentDependencyIdentifier(extension))) { + continue; + } + deploymentDependencies.add( - DependencyUtils.createDeploymentDependency(dependencies, extension)); + DependencyUtils.createDeploymentDependency( + project, + dependencies, + extension, + seenDeploymentDependencies)); } + return deploymentDependencies; }))); }); diff --git a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/dependency/DependencyUtils.java b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/dependency/DependencyUtils.java index 15682e835114d6..a8cb5b6e87198c 100644 --- a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/dependency/DependencyUtils.java +++ b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/dependency/DependencyUtils.java @@ -40,6 +40,7 @@ import io.quarkus.gradle.extension.ConfigurationUtils; import io.quarkus.gradle.extension.ExtensionConstants; import io.quarkus.gradle.tooling.ToolingUtils; +import io.quarkus.gradle.tooling.pom.PomUtils; import io.quarkus.maven.dependency.ArtifactCoords; import io.quarkus.maven.dependency.ArtifactKey; import io.quarkus.maven.dependency.GACT; @@ -349,15 +350,16 @@ public static Dependency create(DependencyHandler dependencies, String condition dependencyCoords.getVersion())); } - public static Dependency createDeploymentDependency( + public static Dependency createDeploymentDependency(Project project, DependencyHandler dependencyHandler, - ExtensionDependency dependency) { + ExtensionDependency dependency, + Set seenDeploymentDependencies) { if (dependency instanceof ProjectExtensionDependency) { ProjectExtensionDependency ped = (ProjectExtensionDependency) dependency; return createDeploymentProjectDependency(dependencyHandler, ped); } else if (dependency instanceof ArtifactExtensionDependency) { ArtifactExtensionDependency aed = (ArtifactExtensionDependency) dependency; - return createArtifactDeploymentDependency(dependencyHandler, aed); + return createArtifactDeploymentDependency(project, dependencyHandler, aed, seenDeploymentDependencies); } throw new IllegalArgumentException("Unknown ExtensionDependency type: " + dependency.getClass().getName()); @@ -376,10 +378,28 @@ private static Dependency createDeploymentProjectDependency(DependencyHandler ha } } - private static Dependency createArtifactDeploymentDependency(DependencyHandler handler, - ArtifactExtensionDependency dependency) { + private static Dependency createArtifactDeploymentDependency( + Project project, + DependencyHandler handler, + ArtifactExtensionDependency dependency, + Set seenDeploymentDependencies) { + + seenDeploymentDependencies.addAll(PomUtils.readDeploymentDependencies(project, dependency.getDeploymentModule())); + return handler.create(dependency.getDeploymentModule().getGroupId() + ":" + dependency.getDeploymentModule().getArtifactId() + ":" + dependency.getDeploymentModule().getVersion()); } + + public static String getDeploymentDependencyIdentifier(ExtensionDependency extension) { + if (extension instanceof ArtifactExtensionDependency) { + ArtifactExtensionDependency aed = (ArtifactExtensionDependency) extension; + return aed.getDeploymentModule().getGroupId() + ":" + aed.getDeploymentModule().getArtifactId(); + } else if (extension instanceof ProjectExtensionDependency) { + ProjectExtensionDependency ped = (ProjectExtensionDependency) extension; + return ped.getDeploymentModule().getGroup() + ":" + ped.getDeploymentModule().getName(); + } + + return null; + } } diff --git a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/pom/PomUtils.java b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/pom/PomUtils.java new file mode 100644 index 00000000000000..0f8af9b74c65c6 --- /dev/null +++ b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/pom/PomUtils.java @@ -0,0 +1,69 @@ +package io.quarkus.gradle.tooling.pom; + +import java.io.FileReader; +import java.nio.charset.StandardCharsets; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Model; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.gradle.api.Project; +import org.gradle.api.artifacts.result.ArtifactResolutionResult; +import org.gradle.api.artifacts.result.ArtifactResult; +import org.gradle.api.artifacts.result.ComponentArtifactsResult; +import org.gradle.api.internal.artifacts.DefaultModuleIdentifier; +import org.gradle.api.internal.artifacts.result.DefaultResolvedArtifactResult; +import org.gradle.internal.component.external.model.DefaultModuleComponentIdentifier; +import org.gradle.maven.MavenModule; +import org.gradle.maven.MavenPomArtifact; + +import io.quarkus.maven.dependency.ArtifactCoords; + +public final class PomUtils { + public static Set readDeploymentDependencies(Project project, ArtifactCoords artifactCoords) { + @SuppressWarnings("unchecked") + ArtifactResolutionResult resolutionResult = project + .getDependencies().createArtifactResolutionQuery() + .forComponents( + new DefaultModuleComponentIdentifier( + DefaultModuleIdentifier.newId( + artifactCoords.getGroupId(), + artifactCoords.getArtifactId()), + artifactCoords.getVersion())) + .withArtifacts(MavenModule.class, MavenPomArtifact.class) + .execute(); + + MavenXpp3Reader pomReader = new MavenXpp3Reader(); + + final Set results = new HashSet<>(); + + for (ComponentArtifactsResult resolvedComponent : resolutionResult.getResolvedComponents()) { + for (ArtifactResult artifact : resolvedComponent.getArtifacts(MavenPomArtifact.class)) { + if (artifact instanceof DefaultResolvedArtifactResult) { + DefaultResolvedArtifactResult resolvedArtifact = (DefaultResolvedArtifactResult) artifact; + + Model pom; + try (FileReader fr = new FileReader(resolvedArtifact.getFile(), StandardCharsets.UTF_8)) { + pom = pomReader.read(fr); + } catch (Exception e) { + project.getLogger().warn("Failed to read pom.xml for " + resolvedArtifact, e); + continue; + } + + for (Dependency pomDependency : pom.getDependencies()) { + if (!Objects.equals("test", pomDependency.getScope())) { + results.add(pomDependency.getGroupId() + ":" + pomDependency.getArtifactId()); + } + } + } + } + } + + return results; + } + + private PomUtils() { + } +} diff --git a/devtools/gradle/gradle/libs.versions.toml b/devtools/gradle/gradle/libs.versions.toml index 87c07810793ae6..34786d72c9233c 100644 --- a/devtools/gradle/gradle/libs.versions.toml +++ b/devtools/gradle/gradle/libs.versions.toml @@ -5,6 +5,8 @@ plugin-publish = "1.2.1" kotlin = "1.9.22" smallrye-config = "3.5.4" +maven = "3.9.6" + junit5 = "5.10.2" assertj = "3.25.3" @@ -22,8 +24,10 @@ quarkus-project-core-extension-codestarts = { module = "io.quarkus:quarkus-proje kotlin-gradle-plugin-api = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin-api", version.ref = "kotlin" } smallrye-config-yaml = { module = "io.smallrye.config:smallrye-config-source-yaml", version.ref = "smallrye-config" } -jackson-databind = {module="com.fasterxml.jackson.core:jackson-databind"} -jackson-dataformat-yaml = {module="com.fasterxml.jackson.dataformat:jackson-dataformat-yaml"} +jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind" } +jackson-dataformat-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml" } + +maven-model = { module = "org.apache.maven:maven-model", version.ref = "maven" } junit-bom = { module = "org.junit:junit-bom", version.ref = "junit5" } junit-api = { module = "org.junit.jupiter:junit-jupiter-api" } diff --git a/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/build.gradle b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/build.gradle new file mode 100644 index 00000000000000..21deaf7f0d7ca6 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/build.gradle @@ -0,0 +1,32 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-resteasy-reactive-jackson' + implementation 'io.quarkus:quarkus-hibernate-reactive-panache' + implementation 'io.quarkus:quarkus-reactive-pg-client' + implementation 'io.quarkus:quarkus-arc' + implementation 'io.quarkus:quarkus-resteasy-reactive' + testImplementation 'io.quarkus:quarkus-junit5' + testImplementation 'io.rest-assured:rest-assured' +} + +group 'org.acme' +version '1.0.0-SNAPSHOT' + +test { + systemProperty "java.util.logging.manager", "org.jboss.logmanager.LogManager" +} diff --git a/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/gradle.properties b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/gradle.properties new file mode 100644 index 00000000000000..ec2b6ef199c2ca --- /dev/null +++ b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/gradle.properties @@ -0,0 +1,2 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus diff --git a/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/settings.gradle b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/settings.gradle new file mode 100644 index 00000000000000..b2d511f9f6a1a1 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/settings.gradle @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() + gradlePluginPortal() + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + } +} + +rootProject.name='code-with-quarkus' diff --git a/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/java/org/acme/GreetingResource.java b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/java/org/acme/GreetingResource.java new file mode 100644 index 00000000000000..6938062ec8ff7e --- /dev/null +++ b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/java/org/acme/GreetingResource.java @@ -0,0 +1,16 @@ +package org.acme; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +@Path("/hello") +public class GreetingResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "Hello from RESTEasy Reactive"; + } +} diff --git a/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/java/org/acme/MyEntity.java b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/java/org/acme/MyEntity.java new file mode 100644 index 00000000000000..a18f8d226cf277 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/java/org/acme/MyEntity.java @@ -0,0 +1,14 @@ + +package org.acme; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import java.util.UUID; + +@Entity +public class MyEntity { + @Id + @GeneratedValue + private UUID id; +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/resources/META-INF/resources/index.html b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/resources/META-INF/resources/index.html new file mode 100644 index 00000000000000..bd66dc4bb5121b --- /dev/null +++ b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/resources/META-INF/resources/index.html @@ -0,0 +1,285 @@ + + + + + code-with-quarkus - 1.0.0-SNAPSHOT + + + +
+
+
+ + + + + quarkus_logo_horizontal_rgb_1280px_reverse + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+

You just made a Quarkus application.

+

This page is served by Quarkus.

+ Visit the Dev UI +

This page: src/main/resources/META-INF/resources/index.html

+

App configuration: src/main/resources/application.properties

+

Static assets: src/main/resources/META-INF/resources/

+

Code: src/main/java

+

Generated starter code:

+
    +
  • + RESTEasy Reactive Easily start your Reactive RESTful Web Services +
    @Path: /hello +
    Related guide +
  • + +
+
+
+

Selected extensions

+
    +
  • RESTEasy Reactive Jackson
  • +
  • Hibernate Reactive with Panache
  • +
  • Reactive PostgreSQL client (guide)
  • +
+
Documentation
+

Practical step-by-step guides to help you achieve a specific goal. Use them to help get your work + done.

+
Set up your IDE
+

Everyone has a favorite IDE they like to use to code. Learn how to configure yours to maximize your + Quarkus productivity.

+
+
+
+ + diff --git a/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/resources/application.properties b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/resources/application.properties new file mode 100644 index 00000000000000..abaaf7722ef5e8 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/main/resources/application.properties @@ -0,0 +1,5 @@ +quarkus.datasource.db-kind = postgresql +quarkus.datasource.username = quarkus_test +quarkus.datasource.password = quarkus_test +quarkus.datasource.reactive.url = vertx-reactive:postgresql://localhost:5432/quarkus_test +#quarkus.datasource.jdbc=false \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/native-test/java/org/acme/GreetingResourceIT.java b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/native-test/java/org/acme/GreetingResourceIT.java new file mode 100644 index 00000000000000..cfa9d1b1aff2bb --- /dev/null +++ b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/native-test/java/org/acme/GreetingResourceIT.java @@ -0,0 +1,8 @@ +package org.acme; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +class GreetingResourceIT extends GreetingResourceTest { + // Execute the same tests but in packaged mode. +} diff --git a/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/test/java/org/acme/GreetingResourceTest.java b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/test/java/org/acme/GreetingResourceTest.java new file mode 100644 index 00000000000000..1e0da3846c90e1 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/maven-exclusion-in-extension-dependency/src/test/java/org/acme/GreetingResourceTest.java @@ -0,0 +1,21 @@ +package org.acme; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +class GreetingResourceTest { + @Test + void testHelloEndpoint() { + given() + .when().get("/hello") + .then() + .statusCode(200) + .body(is("Hello from RESTEasy Reactive")); + } + +} diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/MavenExclusionInExtensionDependencyDevModeTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/MavenExclusionInExtensionDependencyDevModeTest.java new file mode 100644 index 00000000000000..ef27b3d10c9b26 --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/devmode/MavenExclusionInExtensionDependencyDevModeTest.java @@ -0,0 +1,27 @@ +package io.quarkus.gradle.devmode; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * This makes sure that exclusions in POM files of deployment modules are respected. + *

+ * One case where this is critical is when using quarkus-hibernate-reactive. Its deployment + * module takes care of pulling in quarkus-hibernate-orm-deployment where it excludes + * Agroal and Narayana. + *

+ * If that exclusion isn't taken into account by the Gradle plugin, it pulls in + * quarkus-hibernate-orm-deployment on its own, where those other modules aren't excluded, + * which leads to a failure at runtime because Agroal tries to initialize and looks + * for a JDBC driver which isn't typically available in reactive DB scenarios. + */ +public class MavenExclusionInExtensionDependencyDevModeTest extends QuarkusDevGradleTestBase { + @Override + protected String projectDirectoryName() { + return "maven-exclusion-in-extension-dependency"; + } + + @Override + protected void testDevMode() throws Exception { + assertThat(getHttpResponse("/hello")).contains("Hello"); + } +}