Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add very basic support for command line only applications #1301

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,18 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-command-line-runner</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-command-line-aesh</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>

<!-- Quarkus test dependencies -->

Expand Down
20 changes: 20 additions & 0 deletions build-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,26 @@
<artifactId>quarkus-legacy-launcher</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-command-line-runner</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-command-line-runner-runtime</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-command-line-aesh</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-command-line-aesh-runtime</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Quarkus test dependencies -->

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.quarkus.deployment.builditem;

import java.util.function.Consumer;

import org.jboss.builder.item.SimpleBuildItem;

import io.quarkus.gizmo.MethodCreator;
import io.quarkus.gizmo.ResultHandle;

public final class MainAfterStartupBuildItem extends SimpleBuildItem {

private final Consumer<Input> bytecodeCreator;

public MainAfterStartupBuildItem(Consumer<Input> bytecodeCreator) {
this.bytecodeCreator = bytecodeCreator;
}

public Consumer<Input> getBytecodeCreator() {
return bytecodeCreator;
}

public static class Input {
private final MethodCreator doStartMethod;
private final ResultHandle mainArgs;

public Input(MethodCreator doStartMethod, ResultHandle mainArgs) {
this.doStartMethod = doStartMethod;
this.mainArgs = mainArgs;
}

public MethodCreator getDoStartMethod() {
return doStartMethod;
}

public ResultHandle getMainArgs() {
return mainArgs;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.quarkus.deployment.builditem;

import org.jboss.builder.item.SimpleBuildItem;

public final class ShutdownBuildItem extends SimpleBuildItem {
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@
import io.quarkus.deployment.builditem.ClassOutputBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.JavaLibraryPathAdditionalPathBuildItem;
import io.quarkus.deployment.builditem.MainAfterStartupBuildItem;
import io.quarkus.deployment.builditem.MainBytecodeRecorderBuildItem;
import io.quarkus.deployment.builditem.MainClassBuildItem;
import io.quarkus.deployment.builditem.ObjectSubstitutionBuildItem;
import io.quarkus.deployment.builditem.ShutdownBuildItem;
import io.quarkus.deployment.builditem.SslTrustStoreSystemPropertyBuildItem;
import io.quarkus.deployment.builditem.StaticBytecodeRecorderBuildItem;
import io.quarkus.deployment.builditem.SystemPropertyBuildItem;
Expand Down Expand Up @@ -76,6 +78,8 @@ MainClassBuildItem build(List<StaticBytecodeRecorderBuildItem> staticInitTasks,
List<FeatureBuildItem> features,
BuildProducer<ApplicationClassNameBuildItem> appClassNameProducer,
List<BytecodeRecorderObjectLoaderBuildItem> loaders,
Optional<MainAfterStartupBuildItem> mainAfterStartupBuildItem,
Optional<ShutdownBuildItem> shutdownBuildItem,
ClassOutputBuildItem classOutput) {

String appClassName = APP_CLASS + COUNT.incrementAndGet();
Expand Down Expand Up @@ -131,6 +135,7 @@ MainClassBuildItem build(List<StaticBytecodeRecorderBuildItem> staticInitTasks,

mv = file.getMethodCreator("doStart", void.class, String[].class);
mv.setModifiers(Modifier.PROTECTED | Modifier.FINAL);
ResultHandle mainMethodArgs = mv.getMethodParam(0);

// very first thing is to set system props (for run time, which use substitutions for a different
// storage from build-time)
Expand Down Expand Up @@ -214,8 +219,23 @@ MainClassBuildItem build(List<StaticBytecodeRecorderBuildItem> staticInitTasks,
cb.invokeVirtualMethod(ofMethod(Throwable.class, "printStackTrace", void.class), cb.getCaughtException());
cb.invokeVirtualMethod(ofMethod(StartupContext.class, "close", void.class), startupContext);
cb.throwException(RuntimeException.class, "Failed to start quarkus", cb.getCaughtException());

// Application.class: start method after startup
if (mainAfterStartupBuildItem.isPresent()) {
mainAfterStartupBuildItem.get().getBytecodeCreator().accept(
new MainAfterStartupBuildItem.Input(mv, mainMethodArgs));
}

mv.returnValue(null);

// Application class: doPostStart method
if (shutdownBuildItem.isPresent()) {
mv = file.getMethodCreator("doPostStart", void.class);
mv.setModifiers(Modifier.PROTECTED);
mv.invokeSpecialMethod(ofMethod(Application.class, "requestShutdown", void.class), mv.getThis());
mv.returnValue(null);
}

// Application class: stop method

mv = file.getMethodCreator("doStop", void.class);
Expand Down
12 changes: 12 additions & 0 deletions core/deployment/src/main/java/io/quarkus/runner/RuntimeRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.quarkus.deployment.QuarkusAugmentor;
import io.quarkus.deployment.builditem.ApplicationClassNameBuildItem;
import io.quarkus.deployment.builditem.BytecodeTransformerBuildItem;
import io.quarkus.deployment.builditem.ShutdownBuildItem;
import io.quarkus.runtime.Application;
import io.quarkus.runtime.LaunchMode;

Expand Down Expand Up @@ -108,6 +109,17 @@ public void run() {
transformerTarget.setTransformers(functions);
}

try {
// dev mode does not make sense when we a ShutdownBuildItem exists
// because such applications dont stay up
final ShutdownBuildItem shutdownBuildItem = result.consume(ShutdownBuildItem.class);
if ((shutdownBuildItem != null) && (launchMode == LaunchMode.DEVELOPMENT)) {
System.exit(99);
}
} catch (IllegalArgumentException e) {
// there were no ShutdownBuildItem so we can proceed
}

final Application application;
Class<? extends Application> appClass = loader
.loadClass(result.consume(ApplicationClassNameBuildItem.class).getClassName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,15 @@ public final void start(@SuppressWarnings("unused") String[] args) {
} finally {
stateLock.unlock();
}
doPostStart();
}

protected abstract void doStart(String[] args);

protected void doPostStart() {

}

/**
* Stop the application. If another thread is also trying to stop the application, this method waits for that
* thread to finish. Returns immediately if the application is already stopped. If an exception is thrown during
Expand Down Expand Up @@ -222,6 +227,10 @@ private void exit() {
}
}

protected void requestShutdown() {
shutdownRequested = true;
}

private static IllegalStateException interruptedOnAwaitStart() {
return new IllegalStateException("Interrupted while waiting for another thread to start the application");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,22 @@ public void run() {
p.destroy();
}
}, "Development Mode Shutdown Hook"));

int exitCode;
try {
p.waitFor();
exitCode = p.waitFor();
} catch (Exception e) {
p.destroy();
throw e;
}

if (exitCode != 0) {
String message = exitCode == 99 ? //TODO fix: this is pretty lame
"quarkus-dev cannot be used with command line applications"
: "The application did not terminate properly";
throw new RuntimeException(message);
}

} catch (Exception e) {
throw new GradleException("Failed to run", e);
}
Expand Down
11 changes: 10 additions & 1 deletion devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,22 @@ public void run() {
p.destroy();
}
}, "Development Mode Shutdown Hook"));

int exitCode = 0;
try {
p.waitFor();
exitCode = p.waitFor();
} catch (Exception e) {
p.destroy();
throw e;
}

if (exitCode != 0) {
String message = exitCode == 99 ? //TODO fix: this is pretty lame
"quarkus:dev cannot be used with command line applications"
: "The application did not terminate properly";
throw new RuntimeException(message);
}

} catch (Exception e) {
throw new MojoFailureException("Failed to run", e);
}
Expand Down
61 changes: 61 additions & 0 deletions extensions/command-line-aesh/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2018 Red Hat, Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-command-line-aesh-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-command-line-aesh</artifactId>
<name>Quarkus - Command Line Aesh - Deployment</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-command-line-aesh-runtime</artifactId>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.quarkus.claesh.deployment;

import org.jboss.builder.item.MultiBuildItem;

public final class AeshCommandLineRunnerBuildItem extends MultiBuildItem {

private final String className;

public AeshCommandLineRunnerBuildItem(String className) {
this.className = className;
}

public String getClassName() {
return className;
}
}
Loading