diff --git a/core/deployment/src/main/java/io/quarkus/deployment/cmd/RunCommandProcessor.java b/core/deployment/src/main/java/io/quarkus/deployment/cmd/RunCommandProcessor.java index 3617575bf8281..fa38d39f422e0 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/cmd/RunCommandProcessor.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/cmd/RunCommandProcessor.java @@ -13,6 +13,7 @@ import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.pkg.PackageConfig; +import io.quarkus.deployment.pkg.builditem.BuildSystemTargetBuildItem; import io.quarkus.deployment.pkg.builditem.LegacyJarRequiredBuildItem; import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem; import io.quarkus.deployment.pkg.builditem.UberJarRequiredBuildItem; @@ -32,7 +33,8 @@ public void defaultJavaCommand(PackageConfig packageConfig, OutputTargetBuildItem jar, List uberJarRequired, List legacyJarRequired, - BuildProducer cmds) { + BuildProducer cmds, + BuildSystemTargetBuildItem buildSystemTarget) { Path jarPath = null; if (legacyJarRequired.isEmpty() && (!uberJarRequired.isEmpty() @@ -52,7 +54,7 @@ public void defaultJavaCommand(PackageConfig packageConfig, List args = new ArrayList<>(); args.add(determineJavaPath()); - for (Map.Entry e : System.getProperties().entrySet()) { + for (Map.Entry e : buildSystemTarget.getBuildSystemProps().entrySet()) { args.add("-D" + e.getKey().toString() + "=" + e.getValue().toString()); } args.add("-jar"); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/cmd/StartDevServicesAndRunCommandHandler.java b/core/deployment/src/main/java/io/quarkus/deployment/cmd/StartDevServicesAndRunCommandHandler.java new file mode 100644 index 0000000000000..47fe6677b2b57 --- /dev/null +++ b/core/deployment/src/main/java/io/quarkus/deployment/cmd/StartDevServicesAndRunCommandHandler.java @@ -0,0 +1,69 @@ +package io.quarkus.deployment.cmd; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import io.quarkus.builder.BuildResult; +import io.quarkus.deployment.builditem.DevServicesLauncherConfigResultBuildItem; + +public class StartDevServicesAndRunCommandHandler implements BiConsumer { + + @Override + public void accept(Object o, BuildResult buildResult) { + var runCommandActionResult = buildResult.consume(RunCommandActionResultBuildItem.class); + var devServicesLauncherConfigResult = buildResult.consume(DevServicesLauncherConfigResultBuildItem.class); + + // FYI: AugmentAction.performCustomBuild runs in its own classloader + // so we can only pass back instances of those classes in the system classloader + + Consumer> consumer = (Consumer>) o; + + // build up the commands + Map cmds = new HashMap<>(); + for (RunCommandActionBuildItem item : runCommandActionResult.getCommands()) { + List itemList = new ArrayList<>(); + addLaunchCommand(itemList, item, devServicesLauncherConfigResult.getConfig()); + cmds.put(item.getCommandName(), itemList); + } + + consumer.accept(cmds); + } + + private void addLaunchCommand(List list, RunCommandActionBuildItem item, Map devServicesProperties) { + List effectiveArgs; + List originalArgs = item.getArgs(); + if (devServicesProperties.isEmpty()) { + effectiveArgs = originalArgs; + } else { + // here we want to "inject" our dev services configuration into the predetermined launch command + + effectiveArgs = new ArrayList<>(originalArgs.size() + devServicesProperties.size()); + int jarArgIndex = -1; + for (int i = 0; i < originalArgs.size(); i++) { + if (originalArgs.get(i).trim().equals("-jar")) { + jarArgIndex = i; + break; + } + } + if (jarArgIndex == -1) { + effectiveArgs = originalArgs; + } else { + effectiveArgs.addAll(originalArgs.subList(0, jarArgIndex)); + for (var devServiceConfigEntry : devServicesProperties.entrySet()) { + effectiveArgs.add("-D" + devServiceConfigEntry.getKey() + "=" + devServiceConfigEntry.getValue()); + } + effectiveArgs.addAll(originalArgs.subList(jarArgIndex, originalArgs.size())); + } + } + + list.add(effectiveArgs); + list.add(item.getWorkingDirectory()); + list.add(item.getStartedExpression()); + list.add(item.isNeedsLogfile()); + list.add(item.getLogFile()); + } +} diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusRun.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusRun.java index 5935f9d46caea..e4434f5474a1b 100644 --- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusRun.java +++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusRun.java @@ -32,8 +32,9 @@ import io.quarkus.bootstrap.app.CuratedApplication; import io.quarkus.bootstrap.app.QuarkusBootstrap; import io.quarkus.bootstrap.model.ApplicationModel; +import io.quarkus.deployment.builditem.DevServicesLauncherConfigResultBuildItem; import io.quarkus.deployment.cmd.RunCommandActionResultBuildItem; -import io.quarkus.deployment.cmd.RunCommandHandler; +import io.quarkus.deployment.cmd.StartDevServicesAndRunCommandHandler; import io.quarkus.gradle.extension.QuarkusPluginExtension; public abstract class QuarkusRun extends QuarkusBuildTask { @@ -111,13 +112,14 @@ public void runQuarkus() { .setAppArtifact(appModel.getAppArtifact()) .setLocalProjectDiscovery(false) .setIsolateDeployment(true) + .setMode(QuarkusBootstrap.Mode.TEST) .build().bootstrap()) { AugmentAction action = curatedApplication.createAugmentor(); AtomicReference exists = new AtomicReference<>(); AtomicReference tooMany = new AtomicReference<>(); String target = System.getProperty("quarkus.run.target"); - action.performCustomBuild(RunCommandHandler.class.getName(), new Consumer>() { + action.performCustomBuild(StartDevServicesAndRunCommandHandler.class.getName(), new Consumer>() { @Override public void accept(Map cmds) { List cmd = null; @@ -166,7 +168,7 @@ public void accept(Map cmds) { } } }, - RunCommandActionResultBuildItem.class.getName()); + RunCommandActionResultBuildItem.class.getName(), DevServicesLauncherConfigResultBuildItem.class.getName()); if (target != null && !exists.get()) { getProject().getLogger().error("quarkus.run.target " + target + " is not found"); return; diff --git a/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapMojo.java index d2e1457ab4cda..0a70ff33f9bfb 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapMojo.java @@ -8,6 +8,7 @@ import java.util.Map; import java.util.Optional; import java.util.Properties; +import java.util.function.Consumer; import java.util.stream.Stream; import org.apache.maven.AbstractMavenLifecycleParticipant; @@ -26,6 +27,7 @@ import org.eclipse.aether.repository.RemoteRepository; import io.quarkus.bootstrap.app.CuratedApplication; +import io.quarkus.bootstrap.app.QuarkusBootstrap; import io.quarkus.maven.components.BootstrapSessionListener; import io.quarkus.maven.components.ManifestSection; import io.quarkus.maven.dependency.ArtifactKey; @@ -294,6 +296,11 @@ protected CuratedApplication bootstrapApplication(LaunchMode mode) throws MojoEx return bootstrapProvider.bootstrapApplication(this, mode); } + protected CuratedApplication bootstrapApplication(LaunchMode mode, Consumer builderCustomizer) + throws MojoExecutionException { + return bootstrapProvider.bootstrapApplication(this, mode, builderCustomizer); + } + protected Properties getBuildSystemProperties(boolean quarkusOnly) throws MojoExecutionException { return bootstrapProvider.bootstrapper(this).getBuildSystemProperties(this, quarkusOnly); } 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 1177a4b2b933b..f23488af36c87 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/QuarkusBootstrapProvider.java @@ -14,6 +14,7 @@ import java.util.Properties; import java.util.Set; import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Named; @@ -126,7 +127,13 @@ public QuarkusMavenAppBootstrap bootstrapper(QuarkusBootstrapMojo mojo) { public CuratedApplication bootstrapApplication(QuarkusBootstrapMojo mojo, LaunchMode mode) throws MojoExecutionException { - return bootstrapper(mojo).bootstrapApplication(mojo, mode); + return bootstrapApplication(mojo, mode, null); + } + + public CuratedApplication bootstrapApplication(QuarkusBootstrapMojo mojo, LaunchMode mode, + Consumer builderCustomizer) + throws MojoExecutionException { + return bootstrapper(mojo).bootstrapApplication(mojo, mode, builderCustomizer); } public ApplicationModel getResolvedApplicationModel(ArtifactKey projectId, LaunchMode mode, String bootstrapId) { @@ -203,7 +210,8 @@ private MavenArtifactResolver artifactResolver(QuarkusBootstrapMojo mojo, Launch } } - private CuratedApplication doBootstrap(QuarkusBootstrapMojo mojo, LaunchMode mode) + private CuratedApplication doBootstrap(QuarkusBootstrapMojo mojo, LaunchMode mode, + Consumer builderCustomizer) throws MojoExecutionException { final BootstrapAppModelResolver modelResolver = new BootstrapAppModelResolver(artifactResolver(mojo, mode)) @@ -253,6 +261,9 @@ private CuratedApplication doBootstrap(QuarkusBootstrapMojo mojo, LaunchMode mod .setForcedDependencies(forcedDependencies); try { + if (builderCustomizer != null) { + builderCustomizer.accept(builder); + } return builder.build().bootstrap(); } catch (BootstrapException e) { throw new MojoExecutionException("Failed to bootstrap the application", e); @@ -346,15 +357,16 @@ private String toManifestSectionAttributeKey(String section, String key) throws key); } - protected CuratedApplication bootstrapApplication(QuarkusBootstrapMojo mojo, LaunchMode mode) + protected CuratedApplication bootstrapApplication(QuarkusBootstrapMojo mojo, LaunchMode mode, + Consumer builderCustomizer) throws MojoExecutionException { if (mode == LaunchMode.DEVELOPMENT) { - return devApp == null ? devApp = doBootstrap(mojo, mode) : devApp; + return devApp == null ? devApp = doBootstrap(mojo, mode, builderCustomizer) : devApp; } if (mode == LaunchMode.TEST) { - return testApp == null ? testApp = doBootstrap(mojo, mode) : testApp; + return testApp == null ? testApp = doBootstrap(mojo, mode, builderCustomizer) : testApp; } - return prodApp == null ? prodApp = doBootstrap(mojo, mode) : prodApp; + return prodApp == null ? prodApp = doBootstrap(mojo, mode, builderCustomizer) : prodApp; } protected ArtifactCoords managingProject(QuarkusBootstrapMojo mojo) { diff --git a/devtools/maven/src/main/java/io/quarkus/maven/RunMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/RunMojo.java index 1213799c9a121..8f246c035e48b 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/RunMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/RunMojo.java @@ -17,8 +17,11 @@ import io.quarkus.bootstrap.app.AugmentAction; import io.quarkus.bootstrap.app.CuratedApplication; +import io.quarkus.bootstrap.app.QuarkusBootstrap; +import io.quarkus.deployment.builditem.DevServicesLauncherConfigResultBuildItem; import io.quarkus.deployment.cmd.RunCommandActionResultBuildItem; -import io.quarkus.deployment.cmd.RunCommandHandler; +import io.quarkus.deployment.cmd.StartDevServicesAndRunCommandHandler; +import io.quarkus.runtime.LaunchMode; @Mojo(name = "run") public class RunMojo extends QuarkusBootstrapMojo { @@ -47,12 +50,19 @@ protected void doExecute() throws MojoExecutionException, MojoFailureException { } } - try (CuratedApplication curatedApplication = bootstrapApplication()) { + try (CuratedApplication curatedApplication = bootstrapApplication(LaunchMode.NORMAL, + new Consumer() { + @Override + public void accept(QuarkusBootstrap.Builder builder) { + // we need this for dev services + builder.setMode(QuarkusBootstrap.Mode.TEST); + } + })) { AugmentAction action = curatedApplication.createAugmentor(); AtomicReference exists = new AtomicReference<>(); AtomicReference tooMany = new AtomicReference<>(); String target = System.getProperty("quarkus.run.target"); - action.performCustomBuild(RunCommandHandler.class.getName(), new Consumer>() { + action.performCustomBuild(StartDevServicesAndRunCommandHandler.class.getName(), new Consumer>() { @Override public void accept(Map cmds) { List cmd = null; @@ -94,7 +104,7 @@ public void accept(Map cmds) { } } }, - RunCommandActionResultBuildItem.class.getName()); + RunCommandActionResultBuildItem.class.getName(), DevServicesLauncherConfigResultBuildItem.class.getName()); if (target != null && !exists.get()) { getLog().error("quarkus.run.target " + target + " is not found"); return;