Skip to content

Commit

Permalink
Allow quarkus:run to launch DevServices
Browse files Browse the repository at this point in the history
Closes: #40270
  • Loading branch information
geoand committed Apr 25, 2024
1 parent 438c23e commit 1eaecd6
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void defaultJavaCommand(PackageConfig packageConfig,
List<String> args = new ArrayList<>();
args.add(determineJavaPath());

for (Map.Entry<?, ?> e : System.getProperties().entrySet()) {
for (Map.Entry<?, ?> e : System.getProperties().entrySet()) { //TODO: this is almost certainly wrong as it pulls in all the system properties Maven has set
args.add("-D" + e.getKey().toString() + "=" + e.getValue().toString());
}
args.add("-jar");
Expand Down
Original file line number Diff line number Diff line change
@@ -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<Object, BuildResult> {

@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<Map<String, List>> consumer = (Consumer<Map<String, List>>) o;

// build up the commands
Map<String, List> cmds = new HashMap<>();
for (RunCommandActionBuildItem item : runCommandActionResult.getCommands()) {
List<String> itemList = new ArrayList<>();
addLaunchCommand(itemList, item, devServicesLauncherConfigResult.getConfig());
cmds.put(item.getCommandName(), itemList);
}

consumer.accept(cmds);
}

private void addLaunchCommand(List list, RunCommandActionBuildItem item, Map<String, String> devServicesProperties) {
List<String> effectiveArgs;
List<String> 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());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<Boolean> exists = new AtomicReference<>();
AtomicReference<String> tooMany = new AtomicReference<>();
String target = System.getProperty("quarkus.run.target");
action.performCustomBuild(RunCommandHandler.class.getName(), new Consumer<Map<String, List>>() {
action.performCustomBuild(StartDevServicesAndRunCommandHandler.class.getName(), new Consumer<Map<String, List>>() {
@Override
public void accept(Map<String, List> cmds) {
List cmd = null;
Expand Down Expand Up @@ -166,7 +168,7 @@ public void accept(Map<String, List> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -294,6 +296,11 @@ protected CuratedApplication bootstrapApplication(LaunchMode mode) throws MojoEx
return bootstrapProvider.bootstrapApplication(this, mode);
}

protected CuratedApplication bootstrapApplication(LaunchMode mode, Consumer<QuarkusBootstrap.Builder> builderCustomizer)
throws MojoExecutionException {
return bootstrapProvider.bootstrapApplication(this, mode, builderCustomizer);
}

protected Properties getBuildSystemProperties(boolean quarkusOnly) throws MojoExecutionException {
return bootstrapProvider.bootstrapper(this).getBuildSystemProperties(this, quarkusOnly);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<QuarkusBootstrap.Builder> builderCustomizer)
throws MojoExecutionException {
return bootstrapper(mojo).bootstrapApplication(mojo, mode, builderCustomizer);
}

public ApplicationModel getResolvedApplicationModel(ArtifactKey projectId, LaunchMode mode, String bootstrapId) {
Expand Down Expand Up @@ -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<QuarkusBootstrap.Builder> builderCustomizer)
throws MojoExecutionException {

final BootstrapAppModelResolver modelResolver = new BootstrapAppModelResolver(artifactResolver(mojo, mode))
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<QuarkusBootstrap.Builder> 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) {
Expand Down
18 changes: 14 additions & 4 deletions devtools/maven/src/main/java/io/quarkus/maven/RunMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -47,12 +50,19 @@ protected void doExecute() throws MojoExecutionException, MojoFailureException {
}
}

try (CuratedApplication curatedApplication = bootstrapApplication()) {
try (CuratedApplication curatedApplication = bootstrapApplication(LaunchMode.NORMAL,
new Consumer<QuarkusBootstrap.Builder>() {
@Override
public void accept(QuarkusBootstrap.Builder builder) {
// we need this for dev services
builder.setMode(QuarkusBootstrap.Mode.TEST);
}
})) {
AugmentAction action = curatedApplication.createAugmentor();
AtomicReference<Boolean> exists = new AtomicReference<>();
AtomicReference<String> tooMany = new AtomicReference<>();
String target = System.getProperty("quarkus.run.target");
action.performCustomBuild(RunCommandHandler.class.getName(), new Consumer<Map<String, List>>() {
action.performCustomBuild(StartDevServicesAndRunCommandHandler.class.getName(), new Consumer<Map<String, List>>() {
@Override
public void accept(Map<String, List> cmds) {
List cmd = null;
Expand Down Expand Up @@ -94,7 +104,7 @@ public void accept(Map<String, List> 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;
Expand Down

0 comments on commit 1eaecd6

Please sign in to comment.