From c72abd214869b8c6930add0735b57349d8c512ad Mon Sep 17 00:00:00 2001 From: Alexey Loubyansky Date: Thu, 2 Jun 2022 18:31:14 +0200 Subject: [PATCH] Option to enable workspace discovery in NORMAL mode --- .../quarkus/deployment/BootstrapConfig.java | 7 ++++ .../GradleApplicationModelBuilder.java | 33 ++++++++++++------- .../maven/QuarkusBootstrapProvider.java | 13 +++++++- .../quarkus/bootstrap/BootstrapConstants.java | 2 ++ .../java/io/quarkus/maven/it/BuildIT.java | 19 ++++++++++- .../quarkus-ext/deployment/pom.xml | 2 +- .../deployment/AcmeQuarkusExtProcessor.java | 25 ++++++++++++++ .../quarkus-ext/runtime/pom.xml | 2 +- .../java/org/acme/AcmeQuarkusExtRecorder.java | 15 +++++++++ .../src/main/java/org/acme/ModuleList.java | 16 +++++++++ .../src/main/java/org/acme/HelloResource.java | 14 ++++++-- 11 files changed, 130 insertions(+), 18 deletions(-) create mode 100644 integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/src/main/java/org/acme/AcmeQuarkusExtRecorder.java create mode 100644 integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/src/main/java/org/acme/ModuleList.java diff --git a/core/deployment/src/main/java/io/quarkus/deployment/BootstrapConfig.java b/core/deployment/src/main/java/io/quarkus/deployment/BootstrapConfig.java index b3979e5751025..1fd2dbef13595 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/BootstrapConfig.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/BootstrapConfig.java @@ -17,6 +17,13 @@ public class BootstrapConfig { @ConfigItem(defaultValue = "false") boolean effectiveModelBuilder; + /** + * If set to true, workspace discovery will be enabled for all launch modes. + * Usually, workspace discovery is enabled by default only for dev and test modes. + */ + @ConfigItem(defaultValue = "false") + Boolean workspaceDiscovery; + /** * Whether to throw an error, warn or silently ignore misaligned platform BOM imports */ diff --git a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/GradleApplicationModelBuilder.java b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/GradleApplicationModelBuilder.java index 9e13a8996bf6f..6bfd7177c63af 100644 --- a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/GradleApplicationModelBuilder.java +++ b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/tooling/GradleApplicationModelBuilder.java @@ -98,15 +98,24 @@ public Object buildAll(String modelName, ModelParameter parameter, Project proje final Configuration deploymentConfig = classpathBuilder.getDeploymentConfiguration(); final PlatformImports platformImports = classpathBuilder.getPlatformImports(); - final ResolvedDependency appArtifact = getProjectArtifact(project, mode); + boolean workspaceDiscovery = LaunchMode.DEVELOPMENT.equals(mode) || LaunchMode.TEST.equals(mode) + || Boolean.parseBoolean(System.getProperty(BootstrapConstants.QUARKUS_BOOTSTRAP_WORKSPACE_DISCOVERY)); + if (!workspaceDiscovery) { + Object o = project.getProperties().get(BootstrapConstants.QUARKUS_BOOTSTRAP_WORKSPACE_DISCOVERY); + if (o != null) { + workspaceDiscovery = Boolean.parseBoolean(o.toString()); + } + } + + final ResolvedDependency appArtifact = getProjectArtifact(project, workspaceDiscovery); final ApplicationModelBuilder modelBuilder = new ApplicationModelBuilder() .setAppArtifact(appArtifact) .addReloadableWorkspaceModule(appArtifact.getKey()) .setPlatformImports(platformImports); final Map appDependencies = new LinkedHashMap<>(); - collectDependencies(classpathConfig.getResolvedConfiguration(), mode, project, appDependencies, modelBuilder, - appArtifact.getWorkspaceModule().mutable()); + collectDependencies(classpathConfig.getResolvedConfiguration(), workspaceDiscovery, + project, appDependencies, modelBuilder, appArtifact.getWorkspaceModule().mutable()); collectExtensionDependencies(project, deploymentConfig, appDependencies); for (ResolvedDependencyBuilder d : appDependencies.values()) { @@ -115,7 +124,7 @@ public Object buildAll(String modelName, ModelParameter parameter, Project proje return modelBuilder.build(); } - public static ResolvedDependency getProjectArtifact(Project project, LaunchMode mode) { + public static ResolvedDependency getProjectArtifact(Project project, boolean workspaceDiscovery) { final ResolvedDependencyBuilder appArtifact = ResolvedDependencyBuilder.newInstance() .setGroupId(project.getGroup().toString()) .setArtifactId(project.getName()) @@ -133,7 +142,7 @@ public static ResolvedDependency getProjectArtifact(Project project, LaunchMode initProjectModule(project, mainModule, javaConvention.getSourceSets().findByName(SourceSet.MAIN_SOURCE_SET_NAME), SourceSet.MAIN_SOURCE_SET_NAME, ArtifactSources.MAIN); - if (mode.equals(LaunchMode.TEST) || mode.equals(LaunchMode.DEVELOPMENT)) { + if (workspaceDiscovery) { initProjectModule(project, mainModule, javaConvention.getSourceSets().findByName(SourceSet.TEST_SOURCE_SET_NAME), SourceSet.TEST_SOURCE_SET_NAME, ArtifactSources.TEST); } @@ -185,7 +194,7 @@ private void collectExtensionDependencies(Project project, Configuration deploym } private void collectDependencies(ResolvedConfiguration configuration, - LaunchMode mode, Project project, Map appDependencies, + boolean workspaceDiscovery, Project project, Map appDependencies, ApplicationModelBuilder modelBuilder, WorkspaceModule.Mutable wsModule) { final Set resolvedArtifacts = configuration.getResolvedArtifacts(); @@ -197,7 +206,8 @@ private void collectDependencies(ResolvedConfiguration configuration, configuration.getFirstLevelModuleDependencies() .forEach(d -> { - collectDependencies(d, mode, project, appDependencies, artifactFiles, new HashSet<>(), modelBuilder, + collectDependencies(d, workspaceDiscovery, project, appDependencies, artifactFiles, new HashSet<>(), + modelBuilder, wsModule, (byte) (COLLECT_TOP_EXTENSION_RUNTIME_NODES | COLLECT_DIRECT_DEPS | COLLECT_RELOADABLE_MODULES)); }); @@ -238,7 +248,8 @@ private void collectDependencies(ResolvedConfiguration configuration, } } - private void collectDependencies(org.gradle.api.artifacts.ResolvedDependency resolvedDep, LaunchMode mode, Project project, + private void collectDependencies(org.gradle.api.artifacts.ResolvedDependency resolvedDep, boolean workspaceDiscovery, + Project project, Map appDependencies, Set artifactFiles, Set processedModules, ApplicationModelBuilder modelBuilder, WorkspaceModule.Mutable parentModule, byte flags) { @@ -262,8 +273,7 @@ private void collectDependencies(org.gradle.api.artifacts.ResolvedDependency res } PathCollection paths = null; - if ((LaunchMode.DEVELOPMENT.equals(mode) || LaunchMode.TEST.equals(mode)) && - a.getId().getComponentIdentifier() instanceof ProjectComponentIdentifier) { + if (workspaceDiscovery && a.getId().getComponentIdentifier() instanceof ProjectComponentIdentifier) { final Project projectDep = project.getRootProject().findProject( ((ProjectComponentIdentifier) a.getId().getComponentIdentifier()).getProjectPath()); @@ -320,7 +330,8 @@ private void collectDependencies(org.gradle.api.artifacts.ResolvedDependency res processedModules.add(new GACT(resolvedDep.getModuleGroup(), resolvedDep.getModuleName())); for (org.gradle.api.artifacts.ResolvedDependency child : resolvedDep.getChildren()) { if (!processedModules.contains(new GACT(child.getModuleGroup(), child.getModuleName()))) { - collectDependencies(child, mode, project, appDependencies, artifactFiles, processedModules, modelBuilder, + collectDependencies(child, workspaceDiscovery, project, appDependencies, artifactFiles, processedModules, + modelBuilder, projectModule, flags); } } diff --git a/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java index fa37c18c01975..874b80ce7904f 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java @@ -24,6 +24,7 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import io.quarkus.bootstrap.BootstrapConstants; import io.quarkus.bootstrap.BootstrapException; import io.quarkus.bootstrap.app.CuratedApplication; import io.quarkus.bootstrap.app.QuarkusBootstrap; @@ -115,6 +116,14 @@ public void close() throws IOException { } } + private static boolean isWorkspaceDiscovery(QuarkusBootstrapMojo mojo) { + String v = System.getProperty(BootstrapConstants.QUARKUS_BOOTSTRAP_WORKSPACE_DISCOVERY); + if (v == null) { + v = mojo.mavenProject().getProperties().getProperty(BootstrapConstants.QUARKUS_BOOTSTRAP_WORKSPACE_DISCOVERY); + } + return Boolean.parseBoolean(v); + } + public class QuarkusMavenAppBootstrap implements Closeable { private CuratedApplication prodApp; @@ -123,9 +132,11 @@ public class QuarkusMavenAppBootstrap implements Closeable { private MavenArtifactResolver artifactResolver(QuarkusBootstrapMojo mojo, LaunchMode mode) throws MojoExecutionException { + isWorkspaceDiscovery(mojo); try { return MavenArtifactResolver.builder() - .setWorkspaceDiscovery(mode == LaunchMode.DEVELOPMENT || mode == LaunchMode.TEST) + .setWorkspaceDiscovery( + mode == LaunchMode.DEVELOPMENT || mode == LaunchMode.TEST || isWorkspaceDiscovery(mojo)) .setCurrentProject(mojo.mavenProject().getFile().toString()) .setPreferPomsFromWorkspace(mode == LaunchMode.DEVELOPMENT || mode == LaunchMode.TEST) .setRepositorySystem(repoSystem) diff --git a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/BootstrapConstants.java b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/BootstrapConstants.java index 70474377eebe6..6c2aa72680a47 100644 --- a/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/BootstrapConstants.java +++ b/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/bootstrap/BootstrapConstants.java @@ -44,4 +44,6 @@ public interface BootstrapConstants { String PLATFORM_PROPERTIES_ARTIFACT_ID_SUFFIX = "-quarkus-platform-properties"; String PLATFORM_PROPERTY_PREFIX = "platform."; + + String QUARKUS_BOOTSTRAP_WORKSPACE_DISCOVERY = "quarkus.bootstrap.workspace-discovery"; } diff --git a/integration-tests/maven/src/test/java/io/quarkus/maven/it/BuildIT.java b/integration-tests/maven/src/test/java/io/quarkus/maven/it/BuildIT.java index c3ec32fc7baa7..5fab8789d143b 100644 --- a/integration-tests/maven/src/test/java/io/quarkus/maven/it/BuildIT.java +++ b/integration-tests/maven/src/test/java/io/quarkus/maven/it/BuildIT.java @@ -31,6 +31,18 @@ class BuildIT extends MojoTestBase { private RunningInvoker running; private File testDir; + @Test + void testQuarkusBootstrapWorkspaceDiscovery() throws Exception { + testDir = initProject("projects/project-with-extension", "projects/project-with-extension-build"); + running = new RunningInvoker(testDir, false); + MavenProcessInvocationResult result = running + .execute(List.of("clean", "compile", "quarkus:build", "-Dquarkus.bootstrap.workspace-discovery"), Map.of()); + assertThat(result.getProcess().waitFor()).isZero(); + + launch(TestContext.FAST_NO_PREFIX, "/app/hello/local-modules", new File(testDir, "runner"), "", + "[org.acme:acme-common-transitive:1.0-SNAPSHOT, org.acme:acme-common:1.0-SNAPSHOT, org.acme:acme-library:1.0-SNAPSHOT, org.acme:acme-quarkus-ext-deployment:1.0-SNAPSHOT, org.acme:acme-quarkus-ext:1.0-SNAPSHOT]"); + } + @Test void testCustomTestSourceSets() throws MavenInvocationException, IOException, InterruptedException { @@ -179,6 +191,11 @@ private void launch(TestContext context, String outputPrefix, String expectedMes } private void launch(TestContext context, File testDir, String outputPrefix, String expectedMessage) throws IOException { + launch(context, "/hello", testDir, outputPrefix, expectedMessage); + } + + private void launch(TestContext context, String path, File testDir, String outputPrefix, String expectedMessage) + throws IOException { File output = new File(testDir, String.format("target/%s%soutput.log", context.prefix, outputPrefix)); output.createNewFile(); Process process = JarRunnerIT @@ -187,7 +204,7 @@ private void launch(TestContext context, File testDir, String outputPrefix, Stri Collections.emptyList()) .start(); try { - Assertions.assertEquals(expectedMessage, DevModeTestUtils.getHttpResponse("/hello")); + Assertions.assertEquals(expectedMessage, DevModeTestUtils.getHttpResponse(path)); } finally { process.destroy(); } diff --git a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/deployment/pom.xml b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/deployment/pom.xml index 1089a326a64ac..34c85cf51f38c 100644 --- a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/deployment/pom.xml +++ b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/deployment/pom.xml @@ -16,7 +16,7 @@ io.quarkus - quarkus-core-deployment + quarkus-arc-deployment org.acme diff --git a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/deployment/src/main/java/org/acme/quarkus/ext/deployment/AcmeQuarkusExtProcessor.java b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/deployment/src/main/java/org/acme/quarkus/ext/deployment/AcmeQuarkusExtProcessor.java index 693fa12d82f37..7723e112b407d 100644 --- a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/deployment/src/main/java/org/acme/quarkus/ext/deployment/AcmeQuarkusExtProcessor.java +++ b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/deployment/src/main/java/org/acme/quarkus/ext/deployment/AcmeQuarkusExtProcessor.java @@ -1,7 +1,19 @@ package org.acme.quarkus.ext.deployment; +import java.util.stream.Collectors; + +import javax.inject.Singleton; + +import io.quarkus.arc.deployment.SyntheticBeanBuildItem; import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.annotations.ExecutionTime; +import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem; +import io.quarkus.maven.dependency.Dependency; + +import org.acme.AcmeQuarkusExtRecorder; +import org.acme.ModuleList; class AcmeQuarkusExtProcessor { @@ -12,4 +24,17 @@ FeatureBuildItem feature() { return new FeatureBuildItem(FEATURE); } + @BuildStep + @Record(ExecutionTime.STATIC_INIT) + SyntheticBeanBuildItem syntheticBean(AcmeQuarkusExtRecorder recorder, CurateOutcomeBuildItem curateOutcome) { + var localModules = curateOutcome.getApplicationModel().getDependencies().stream() + .filter(Dependency::isWorkspaceModule) + .map(Dependency::toCompactCoords) + .sorted() + .collect(Collectors.toList()); + return SyntheticBeanBuildItem.configure(ModuleList.class) + .scope(Singleton.class) + .runtimeValue(recorder.initLocalModules(localModules)) + .done(); + } } diff --git a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/pom.xml b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/pom.xml index 82ae9cab0e8c7..cd33202db2002 100644 --- a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/pom.xml +++ b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/pom.xml @@ -20,7 +20,7 @@ io.quarkus - quarkus-core + quarkus-arc diff --git a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/src/main/java/org/acme/AcmeQuarkusExtRecorder.java b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/src/main/java/org/acme/AcmeQuarkusExtRecorder.java new file mode 100644 index 0000000000000..7aef3d45268d9 --- /dev/null +++ b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/src/main/java/org/acme/AcmeQuarkusExtRecorder.java @@ -0,0 +1,15 @@ +package org.acme; + +import java.util.List; + +import io.quarkus.arc.runtime.BeanContainer; +import io.quarkus.runtime.RuntimeValue; +import io.quarkus.runtime.annotations.Recorder; + +@Recorder +public class AcmeQuarkusExtRecorder { + + public RuntimeValue initLocalModules(List localModules) { + return new RuntimeValue<>(new ModuleList(localModules)); + } +} diff --git a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/src/main/java/org/acme/ModuleList.java b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/src/main/java/org/acme/ModuleList.java new file mode 100644 index 0000000000000..d97c628feb9a7 --- /dev/null +++ b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/quarkus-ext/runtime/src/main/java/org/acme/ModuleList.java @@ -0,0 +1,16 @@ +package org.acme; + +import java.util.List; + +public class ModuleList { + + private final List localModules; + + public ModuleList(List localModules) { + this.localModules = localModules; + } + + public List getModules() { + return localModules; + } +} \ No newline at end of file diff --git a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/runner/src/main/java/org/acme/HelloResource.java b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/runner/src/main/java/org/acme/HelloResource.java index 5ab2bf6d341c6..9458c5c27079f 100644 --- a/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/runner/src/main/java/org/acme/HelloResource.java +++ b/integration-tests/maven/src/test/resources-filtered/projects/project-with-extension/runner/src/main/java/org/acme/HelloResource.java @@ -2,14 +2,12 @@ import org.eclipse.microprofile.config.inject.ConfigProperty; + 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 java.io.IOException; -import java.net.URL; -import java.util.Enumeration; @Path("/hello") public class HelloResource { @@ -21,6 +19,9 @@ public class HelloResource { @ConfigProperty(name = "greeting") String greeting; + @Inject + ModuleList moduleList; + public HelloResource(CommonBean common, LibraryBean library) { this.common = java.util.Objects.requireNonNull(common); this.library = java.util.Objects.requireNonNull(library); @@ -38,4 +39,11 @@ public String hello() { public String greeting() { return greeting; } + + @GET + @Path("/local-modules") + @Produces(MediaType.TEXT_PLAIN) + public String localModules() { + return moduleList.getModules().toString(); + } }