Skip to content

Commit

Permalink
Merge pull request quarkusio#9765 from stuartwdouglas/remote-dev-mutable
Browse files Browse the repository at this point in the history
Allow mutable applications to be started in dev mode
  • Loading branch information
aloubyansky authored Jun 18, 2020
2 parents 27c382e + b39620b commit a5c5f91
Show file tree
Hide file tree
Showing 73 changed files with 2,403 additions and 1,124 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ jobs:
name: Windows JDK 11 JVM Tests
needs: build-jdk11
runs-on: windows-latest
timeout-minutes: 130
timeout-minutes: 150
env:
MAVEN_OPTS: -Xmx1408m

Expand Down
57 changes: 57 additions & 0 deletions core/builder/src/test/java/io/quarkus/builder/BasicTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

import java.util.concurrent.atomic.AtomicBoolean;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;

import io.quarkus.builder.item.SimpleBuildItem;

Expand Down Expand Up @@ -41,6 +43,61 @@ public void execute(final BuildContext context) {
assertNotNull(result.consume(DummyItem.class));
}

@Test
public void testFailure() throws ChainBuildException, BuildException {
final BuildChainBuilder builder = BuildChain.builder();
final AtomicBoolean ran = new AtomicBoolean();
BuildStepBuilder stepBuilder = builder.addBuildStep(new BuildStep() {
@Override
public void execute(final BuildContext context) {
throw new NoClassDefFoundError();
}
});
stepBuilder.produces(DummyItem.class);
stepBuilder.build();
builder.addFinal(DummyItem.class);
BuildChain chain = builder.build();
Assertions.assertThrows(BuildException.class, new Executable() {
@Override
public void execute() throws Throwable {
chain.createExecutionBuilder("my-app.jar").execute();
}
});
}

@Test
public void testFailure2() throws ChainBuildException, BuildException {
final BuildChainBuilder builder = BuildChain.builder();
BuildStepBuilder stepBuilder = builder.addBuildStep(new BuildStep() {
@Override
public void execute(final BuildContext context) {
throw new NoClassDefFoundError();
}
});

final AtomicBoolean ran = new AtomicBoolean();
stepBuilder.produces(DummyItem.class);
stepBuilder.build();
stepBuilder = builder.addBuildStep(new BuildStep() {
@Override
public void execute(final BuildContext context) {
ran.set(true);
}
});
stepBuilder.consumes(DummyItem.class);
stepBuilder.produces(DummyItem2.class);
stepBuilder.build();
builder.addFinal(DummyItem2.class);
BuildChain chain = builder.build();
Assertions.assertFalse(ran.get());
Assertions.assertThrows(BuildException.class, new Executable() {
@Override
public void execute() throws Throwable {
chain.createExecutionBuilder("my-app.jar").execute();
}
});
}

@Test
public void testLinked() throws ChainBuildException, BuildException {
final BuildChainBuilder builder = BuildChain.builder();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.quarkus.deployment.dev;

import java.util.List;
import java.util.Map;

import io.quarkus.bootstrap.model.AppArtifactKey;

public class CurrentClassState {

private final List<CurrentModuleState> currentModuleState;

public CurrentClassState(List<CurrentModuleState> currentModuleState) {
this.currentModuleState = currentModuleState;
}

public List<CurrentModuleState> getCurrentModuleState() {
return currentModuleState;
}

public static class CurrentModuleState {

private final AppArtifactKey module;
private final Map<String, String> fileToHash;

public CurrentModuleState(AppArtifactKey module, Map<String, String> fileToHash) {
this.module = module;
this.fileToHash = fileToHash;
}

public AppArtifactKey getModule() {
return module;
}

public Map<String, String> getFileToHash() {
return fileToHash;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.quarkus.bootstrap.app.QuarkusBootstrap;
import io.quarkus.bootstrap.model.AppArtifactKey;

/**
* Object that is used to pass context data from the plugin doing the invocation
* into the dev mode process using java serialization.
Expand Down Expand Up @@ -46,6 +50,11 @@ public class DevModeContext implements Serializable {
private List<String> compilerPluginArtifacts;
private List<String> compilerPluginsOptions;

private String alternateEntryPoint;
private QuarkusBootstrap.Mode mode = QuarkusBootstrap.Mode.DEV;
private String baseName;
private final Set<AppArtifactKey> localArtifacts = new HashSet<>();

public boolean isLocalProjectDiscovery() {
return localProjectDiscovery;
}
Expand All @@ -55,6 +64,15 @@ public DevModeContext setLocalProjectDiscovery(boolean localProjectDiscovery) {
return this;
}

public String getAlternateEntryPoint() {
return alternateEntryPoint;
}

public DevModeContext setAlternateEntryPoint(String alternateEntryPoint) {
this.alternateEntryPoint = alternateEntryPoint;
return this;
}

public ModuleInfo getApplicationRoot() {
return applicationRoot;
}
Expand Down Expand Up @@ -184,31 +202,53 @@ public List<ModuleInfo> getAllModules() {
return ret;
}

public QuarkusBootstrap.Mode getMode() {
return mode;
}

public void setMode(QuarkusBootstrap.Mode mode) {
this.mode = mode;
}

public String getBaseName() {
return baseName;
}

public void setBaseName(String baseName) {
this.baseName = baseName;
}

public Set<AppArtifactKey> getLocalArtifacts() {
return localArtifacts;
}

public static class ModuleInfo implements Serializable {

private final AppArtifactKey appArtifactKey;
private final String name;
private final String projectDirectory;
private final Set<String> sourcePaths;
private final String classesPath;
private final String resourcePath;
private final String resourcesOutputPath;

public ModuleInfo(
public ModuleInfo(AppArtifactKey appArtifactKey,
String name,
String projectDirectory,
Set<String> sourcePaths,
String classesPath,
String resourcePath) {
this(name, projectDirectory, sourcePaths, classesPath, resourcePath, classesPath);
this(appArtifactKey, name, projectDirectory, sourcePaths, classesPath, resourcePath, classesPath);
}

public ModuleInfo(
String name,
AppArtifactKey appArtifactKey, String name,
String projectDirectory,
Set<String> sourcePaths,
String classesPath,
String resourcePath,
String resourceOutputPath) {
this.appArtifactKey = appArtifactKey;
this.name = name;
this.projectDirectory = projectDirectory;
this.sourcePaths = sourcePaths == null ? new LinkedHashSet<>() : new LinkedHashSet<>(sourcePaths);
Expand Down Expand Up @@ -244,6 +284,10 @@ public String getResourcePath() {
public String getResourcesOutputPath() {
return resourcesOutputPath;
}

public AppArtifactKey getAppArtifactKey() {
return appArtifactKey;
}
}

public boolean isEnablePreview() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.quarkus.bootstrap.app.AdditionalDependency;
import io.quarkus.bootstrap.app.CuratedApplication;
import io.quarkus.bootstrap.app.QuarkusBootstrap;
import io.quarkus.bootstrap.model.AppArtifactKey;
import io.quarkus.bootstrap.model.PathsCollection;
import io.quarkus.dev.appstate.ApplicationStateNotification;

Expand Down Expand Up @@ -96,15 +97,20 @@ public void start() throws Exception {

QuarkusBootstrap.Builder bootstrapBuilder = QuarkusBootstrap.builder()
.setApplicationRoot(appRoots.build())
.setTargetDirectory(context.getDevModeRunnerJarFile().getParentFile().toPath())
.setIsolateDeployment(true)
.setLocalProjectDiscovery(context.isLocalProjectDiscovery())
.addAdditionalDeploymentArchive(path)
.setMode(QuarkusBootstrap.Mode.DEV);
.setBaseName(context.getBaseName())
.setMode(context.getMode());
if (context.getProjectDir() != null) {
bootstrapBuilder.setProjectRoot(context.getProjectDir().toPath());
} else {
bootstrapBuilder.setProjectRoot(new File(".").toPath());
}
for (AppArtifactKey i : context.getLocalArtifacts()) {
bootstrapBuilder.addLocalArtifact(i);
}

for (DevModeContext.ModuleInfo i : context.getAllModules()) {
if (i.getClassesPath() != null) {
Expand All @@ -123,10 +129,12 @@ public void start() throws Exception {
buildSystemProperties.putAll(context.getBuildSystemProperties());
bootstrapBuilder.setBuildSystemProperties(buildSystemProperties);
curatedApplication = bootstrapBuilder.setTest(context.isTest()).build().bootstrap();
realCloseable = (Closeable) curatedApplication.runInAugmentClassLoader(IsolatedDevModeMain.class.getName(),
realCloseable = (Closeable) curatedApplication.runInAugmentClassLoader(
context.getAlternateEntryPoint() == null ? IsolatedDevModeMain.class.getName()
: context.getAlternateEntryPoint(),
Collections.singletonMap(DevModeContext.class.getName(), context));
} catch (Throwable t) {
log.error("Quarkus dev mode failed to start in curation phase", t);
log.error("Quarkus dev mode failed to start", t);
throw new RuntimeException(t);
//System.exit(1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public void accept(CuratedApplication curatedApplication, Map<String, Object> st
}

private DevModeContext.ModuleInfo toModule(LocalProject project) {
return new DevModeContext.ModuleInfo(project.getArtifactId(), project.getDir().toAbsolutePath().toString(),
return new DevModeContext.ModuleInfo(project.getKey(), project.getArtifactId(),
project.getDir().toAbsolutePath().toString(),
Collections.singleton(project.getSourcesSourcesDir().toAbsolutePath().toString()),
project.getClassesDir().toAbsolutePath().toString(),
project.getResourcesSourcesDir().toAbsolutePath().toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -41,13 +42,13 @@
public class IsolatedDevModeMain implements BiConsumer<CuratedApplication, Map<String, Object>>, Closeable {

private static final Logger log = Logger.getLogger(DevModeMain.class);
public static final String APP_ROOT = "app-root";

private volatile DevModeContext context;

private final List<HotReplacementSetup> hotReplacementSetups = new ArrayList<>();
private static volatile RunningQuarkusApplication runner;
static volatile Throwable deploymentProblem;
static volatile Throwable compileProblem;
static volatile RuntimeUpdatesProcessor runtimeUpdatesProcessor;
private static volatile CuratedApplication curatedApplication;
private static volatile AugmentAction augmentAction;
Expand Down Expand Up @@ -148,7 +149,7 @@ public synchronized void restartApp(Set<String> changedResources) {
}
}

private RuntimeUpdatesProcessor setupRuntimeCompilation(DevModeContext context, CuratedApplication application)
private RuntimeUpdatesProcessor setupRuntimeCompilation(DevModeContext context, Path appRoot)
throws Exception {
if (!context.getAllModules().isEmpty()) {
ServiceLoader<CompilationProvider> serviceLoader = ServiceLoader.load(CompilationProvider.class);
Expand All @@ -165,7 +166,8 @@ private RuntimeUpdatesProcessor setupRuntimeCompilation(DevModeContext context,
log.error("Failed to create compiler, runtime compilation will be unavailable", e);
return null;
}
RuntimeUpdatesProcessor processor = new RuntimeUpdatesProcessor(context, compiler, this);
RuntimeUpdatesProcessor processor = new RuntimeUpdatesProcessor(appRoot, context, compiler,
this::restartApp, null);

for (HotReplacementSetup service : ServiceLoader.load(HotReplacementSetup.class,
curatedApplication.getBaseRuntimeClassLoader())) {
Expand Down Expand Up @@ -286,17 +288,18 @@ public boolean test(String s) {
}).produces(ApplicationClassPredicateBuildItem.class).build();
}
}));
runtimeUpdatesProcessor = setupRuntimeCompilation(context, o);
runtimeUpdatesProcessor = setupRuntimeCompilation(context, (Path) o2.get(APP_ROOT));
if (runtimeUpdatesProcessor != null) {
runtimeUpdatesProcessor.checkForFileChange();
runtimeUpdatesProcessor.checkForChangedClasses();
}
firstStart();

// doStart(false, Collections.emptySet());
if (deploymentProblem != null || compileProblem != null) {
if (deploymentProblem != null || runtimeUpdatesProcessor.getCompileProblem() != null) {
if (context.isAbortOnFailedStart()) {
throw new RuntimeException(deploymentProblem == null ? compileProblem : deploymentProblem);
throw new RuntimeException(
deploymentProblem == null ? runtimeUpdatesProcessor.getCompileProblem() : deploymentProblem);
}
}
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
Expand Down
Loading

0 comments on commit a5c5f91

Please sign in to comment.