From c35794824badf906a177d4b4798d438bb92b0af1 Mon Sep 17 00:00:00 2001 From: Stuart Douglas Date: Sun, 27 Oct 2019 12:08:44 +1100 Subject: [PATCH] Restart app on pom.xml change Unlike other hot replacement this simply watches the pom.xml files, and reloads the complete application on change. This means there is a short period where the app in unavailible. Fixes #4871 --- .../main/java/io/quarkus/maven/DevMojo.java | 299 +++++++++++------- .../java/io/quarkus/maven/it/DevMojoIT.java | 78 +++-- 2 files changed, 242 insertions(+), 135 deletions(-) diff --git a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java index a7a8eef1fac07..e70d77a2c6d9d 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/DevMojo.java @@ -17,6 +17,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -239,41 +241,201 @@ public void execute() throws MojoFailureException, MojoExecutionException { String javaTool = JavaBinFinder.findBin(); getLog().debug("Using javaTool: " + javaTool); args.add(javaTool); - String debugSuspend = "n"; if (this.suspend != null) { switch (this.suspend.toLowerCase(Locale.ENGLISH)) { case "n": case "false": { - debugSuspend = "n"; + suspend = "n"; break; } case "y": case "true": { - debugSuspend = "y"; + suspend = "y"; break; } default: { getLog().warn( "Ignoring invalid value \"" + suspend + "\" for \"suspend\" param and defaulting to \"n\""); + suspend = "n"; break; } } + } else { + suspend = "n"; + } + + boolean useDebugMode = true; + // debug mode not specified + // make sure 5005 is not used, we don't want to just fail if something else is using it + try (Socket socket = new Socket(InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }), 5005)) { + getLog().error("Port 5005 in use, not starting in debug mode"); + useDebugMode = false; + } catch (IOException e) { + } + + if (jvmArgs != null) { + args.addAll(Arrays.asList(jvmArgs.split(" "))); + } + + // the following flags reduce startup time and are acceptable only for dev purposes + args.add("-XX:TieredStopAtLevel=1"); + if (!preventnoverify) { + args.add("-Xverify:none"); } + + DevModeRunner runner = new DevModeRunner(args, useDebugMode); + + runner.prepare(); + runner.run(); + long nextCheck = System.currentTimeMillis() + 100; + Map pomFiles = readPomFileTimestamps(runner); + for (;;) { + //we never suspend after the first run + suspend = "n"; + long sleep = Math.max(0, nextCheck - System.currentTimeMillis()) + 1; + Thread.sleep(sleep); + if (System.currentTimeMillis() > nextCheck) { + nextCheck = System.currentTimeMillis() + 100; + if (!runner.process.isAlive()) { + return; + } + boolean changed = false; + for (Map.Entry e : pomFiles.entrySet()) { + long t = Files.getLastModifiedTime(e.getKey()).toMillis(); + if (t > e.getValue()) { + changed = true; + pomFiles.put(e.getKey(), t); + } + } + if (changed) { + DevModeRunner newRunner = new DevModeRunner(args, useDebugMode); + try { + newRunner.prepare(); + } catch (Exception e) { + getLog().info("Could not load changed pom.xml file, changes not applied"); + continue; + } + runner.stop(); + newRunner.run(); + runner = newRunner; + } + } + + } + + } catch (Exception e) { + throw new MojoFailureException("Failed to run", e); + } + } + + private Map readPomFileTimestamps(DevModeRunner runner) throws IOException { + Map ret = new HashMap<>(); + for (Path i : runner.getPomFiles()) { + ret.put(i, Files.getLastModifiedTime(i).toMillis()); + } + return ret; + } + + private String getSourceEncoding() { + Object sourceEncodingProperty = project.getProperties().get("project.build.sourceEncoding"); + if (sourceEncodingProperty != null) { + return (String) sourceEncodingProperty; + } + return null; + } + + private void addProject(DevModeContext devModeContext, LocalProject localProject) { + + String projectDirectory = null; + Set sourcePaths = null; + String classesPath = null; + String resourcePath = null; + + final MavenProject mavenProject = session.getProjectMap().get( + String.format("%s:%s:%s", localProject.getGroupId(), localProject.getArtifactId(), localProject.getVersion())); + + if (mavenProject == null) { + projectDirectory = localProject.getDir().toAbsolutePath().toString(); + Path sourcePath = localProject.getSourcesSourcesDir().toAbsolutePath(); + if (Files.isDirectory(sourcePath)) { + sourcePaths = Collections.singleton( + sourcePath.toString()); + } else { + sourcePaths = Collections.emptySet(); + } + } else { + projectDirectory = mavenProject.getBasedir().getPath(); + sourcePaths = mavenProject.getCompileSourceRoots().stream() + .map(Paths::get) + .filter(Files::isDirectory) + .map(src -> src.toAbsolutePath().toString()) + .collect(Collectors.toSet()); + } + + Path classesDir = localProject.getClassesDir(); + if (Files.isDirectory(classesDir)) { + classesPath = classesDir.toAbsolutePath().toString(); + } + Path resourcesSourcesDir = localProject.getResourcesSourcesDir(); + if (Files.isDirectory(resourcesSourcesDir)) { + resourcePath = resourcesSourcesDir.toAbsolutePath().toString(); + } + DevModeContext.ModuleInfo moduleInfo = new DevModeContext.ModuleInfo( + localProject.getArtifactId(), + projectDirectory, + sourcePaths, + classesPath, + resourcePath); + devModeContext.getModules().add(moduleInfo); + } + + private void addToClassPaths(StringBuilder classPathManifest, DevModeContext classPath, File file) { + URI uri = file.toPath().toAbsolutePath().toUri(); + try { + classPath.getClassPath().add(uri.toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + String path = uri.getRawPath(); + if (PropertyUtils.isWindows()) { + if (path.length() > 2 && Character.isLetter(path.charAt(0)) && path.charAt(1) == ':') { + path = "/" + path; + } + } + classPathManifest.append(path); + if (file.isDirectory() && path.charAt(path.length() - 1) != '/') { + classPathManifest.append("/"); + } + classPathManifest.append(" "); + } + + class DevModeRunner { + + private final List args; + private Process process; + private Set pomFiles = new HashSet<>(); + private final boolean useDebugMode; + + DevModeRunner(List args, boolean useDebugMode) { + this.args = new ArrayList<>(args); + this.useDebugMode = useDebugMode; + } + + /** + * Attempts to prepare the dev mode runner. + */ + void prepare() throws Exception { if (debug == null) { - // debug mode not specified - // make sure 5005 is not used, we don't want to just fail if something else is using it - try (Socket socket = new Socket(InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }), 5005)) { - getLog().error("Port 5005 in use, not starting in debug mode"); - } catch (IOException e) { + if (useDebugMode) { args.add("-Xdebug"); - args.add("-Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=" + debugSuspend); + args.add("-Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=" + suspend); } } else if (debug.toLowerCase().equals("client")) { args.add("-Xdebug"); - args.add("-Xrunjdwp:transport=dt_socket,address=localhost:5005,server=n,suspend=" + debugSuspend); + args.add("-Xrunjdwp:transport=dt_socket,address=localhost:5005,server=n,suspend=" + suspend); } else if (debug.toLowerCase().equals("true")) { args.add("-Xdebug"); - args.add("-Xrunjdwp:transport=dt_socket,address=localhost:5005,server=y,suspend=" + debugSuspend); + args.add("-Xrunjdwp:transport=dt_socket,address=localhost:5005,server=y,suspend=" + suspend); } else if (!debug.toLowerCase().equals("false")) { try { int port = Integer.parseInt(debug); @@ -281,22 +443,12 @@ public void execute() throws MojoFailureException, MojoExecutionException { throw new MojoFailureException("The specified debug port must be greater than 0"); } args.add("-Xdebug"); - args.add("-Xrunjdwp:transport=dt_socket,address=" + port + ",server=y,suspend=" + debugSuspend); + args.add("-Xrunjdwp:transport=dt_socket,address=" + port + ",server=y,suspend=" + suspend); } catch (NumberFormatException e) { throw new MojoFailureException( "Invalid value for debug parameter: " + debug + " must be true|false|client|{port}"); } } - if (jvmArgs != null) { - args.addAll(Arrays.asList(jvmArgs.split(" "))); - } - - // the following flags reduce startup time and are acceptable only for dev purposes - args.add("-XX:TieredStopAtLevel=1"); - if (!preventnoverify) { - args.add("-Xverify:none"); - } - //build a class-path string for the base platform //this stuff does not change // Do not include URIs in the manifest, because some JVMs do not like that @@ -357,6 +509,9 @@ public void execute() throws MojoFailureException, MojoExecutionException { addProject(devModeContext, project); } } + for (LocalProject i : localProject.getSelfWithLocalDeps()) { + pomFiles.add(i.getDir().resolve("pom.xml")); + } /* * TODO: support multiple resources dirs for config hot deployment @@ -375,6 +530,9 @@ public void execute() throws MojoFailureException, MojoExecutionException { .build()) .setDevMode(true) .resolveModel(localProject.getAppArtifact()); + if (appModel.getAllDependencies().isEmpty()) { + throw new RuntimeException("Unable to resolve application dependencies"); + } } catch (Exception e) { throw new MojoExecutionException("Failed to resolve Quarkus application model", e); } @@ -453,6 +611,14 @@ public void execute() throws MojoFailureException, MojoExecutionException { args.add("-jar"); args.add(tempFile.getAbsolutePath()); + + } + + public Set getPomFiles() { + return pomFiles; + } + + public void run() throws Exception { // Display the launch command line in debug mode getLog().debug("Launching JVM with command line: " + args.toString()); ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0])); @@ -460,100 +626,21 @@ public void execute() throws MojoFailureException, MojoExecutionException { pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); pb.redirectInput(ProcessBuilder.Redirect.INHERIT); pb.directory(workingDir); - Process p = pb.start(); + process = pb.start(); //https://github.com/quarkusio/quarkus/issues/232 Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { - p.destroy(); + process.destroy(); } }, "Development Mode Shutdown Hook")); - try { - int ret = p.waitFor(); - if (ret != 0) { - throw new MojoFailureException("JVM exited with error code: " + ret); - } - } catch (Exception e) { - p.destroy(); - throw e; - } - - } catch (Exception e) { - throw new MojoFailureException("Failed to run", e); } - } - private String getSourceEncoding() { - Object sourceEncodingProperty = project.getProperties().get("project.build.sourceEncoding"); - if (sourceEncodingProperty != null) { - return (String) sourceEncodingProperty; + public void stop() throws InterruptedException { + process.destroy(); + process.waitFor(); } - return null; - } - private void addProject(DevModeContext devModeContext, LocalProject localProject) { - - String projectDirectory = null; - Set sourcePaths = null; - String classesPath = null; - String resourcePath = null; - - final MavenProject mavenProject = session.getProjectMap().get( - String.format("%s:%s:%s", localProject.getGroupId(), localProject.getArtifactId(), localProject.getVersion())); - - if (mavenProject == null) { - projectDirectory = localProject.getDir().toAbsolutePath().toString(); - Path sourcePath = localProject.getSourcesSourcesDir().toAbsolutePath(); - if (Files.isDirectory(sourcePath)) { - sourcePaths = Collections.singleton( - sourcePath.toString()); - } else { - sourcePaths = Collections.emptySet(); - } - } else { - projectDirectory = mavenProject.getBasedir().getPath(); - sourcePaths = mavenProject.getCompileSourceRoots().stream() - .map(Paths::get) - .filter(Files::isDirectory) - .map(src -> src.toAbsolutePath().toString()) - .collect(Collectors.toSet()); - } - - Path classesDir = localProject.getClassesDir(); - if (Files.isDirectory(classesDir)) { - classesPath = classesDir.toAbsolutePath().toString(); - } - Path resourcesSourcesDir = localProject.getResourcesSourcesDir(); - if (Files.isDirectory(resourcesSourcesDir)) { - resourcePath = resourcesSourcesDir.toAbsolutePath().toString(); - } - DevModeContext.ModuleInfo moduleInfo = new DevModeContext.ModuleInfo( - localProject.getArtifactId(), - projectDirectory, - sourcePaths, - classesPath, - resourcePath); - devModeContext.getModules().add(moduleInfo); - } - - private void addToClassPaths(StringBuilder classPathManifest, DevModeContext classPath, File file) { - URI uri = file.toPath().toAbsolutePath().toUri(); - try { - classPath.getClassPath().add(uri.toURL()); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - String path = uri.getRawPath(); - if (PropertyUtils.isWindows()) { - if (path.length() > 2 && Character.isLetter(path.charAt(0)) && path.charAt(1) == ':') { - path = "/" + path; - } - } - classPathManifest.append(path); - if (file.isDirectory() && path.charAt(path.length() - 1) != '/') { - classPathManifest.append("/"); - } - classPathManifest.append(" "); } } diff --git a/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java b/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java index f7882435b327e..d4fefec871403 100644 --- a/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java +++ b/integration-tests/maven/src/test/java/io/quarkus/maven/it/DevMojoIT.java @@ -67,11 +67,11 @@ public void testThatTheApplicationIsReloadedOnJavaChange() throws MavenInvocatio // Wait until we get "uuid" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/app/hello").contains(uuid)); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .pollInterval(1, TimeUnit.SECONDS) .until(source::isFile); @@ -79,10 +79,30 @@ public void testThatTheApplicationIsReloadedOnJavaChange() throws MavenInvocatio // Wait until we get "carambar" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/app/hello").contains("carambar")); } + @Test + public void testThatTheApplicationIsReloadedOnPomChange() throws MavenInvocationException, IOException { + testDir = initProject("projects/classic", "projects/project-classic-run-pom-change"); + runAndCheck(); + + // Edit the pom.xml. + File source = new File(testDir, "pom.xml"); + filter(source, ImmutableMap.of("", "\n" + + " \n" + + " io.quarkus\n" + + " quarkus-smallrye-openapi\n" + + " ${quarkus.version}\n" + + " ")); + + // Wait until we get "uuid" + await() + .pollDelay(100, TimeUnit.MILLISECONDS) + .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/openapi").contains("hello")); + } + @Test public void testThatTheApplicationIsReloadedMultiModule() throws MavenInvocationException, IOException { testDir = initProject("projects/multimodule", "projects/multimodule-with-deps"); @@ -95,11 +115,11 @@ public void testThatTheApplicationIsReloadedMultiModule() throws MavenInvocation // Wait until we get "uuid" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/app/hello").contains(uuid)); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .pollInterval(1, TimeUnit.SECONDS) .until(source::isFile); @@ -107,7 +127,7 @@ public void testThatTheApplicationIsReloadedMultiModule() throws MavenInvocation // Wait until we get "carambar" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/app/hello").contains("carambar")); // Create a new resource @@ -116,21 +136,21 @@ public void testThatTheApplicationIsReloadedMultiModule() throws MavenInvocation "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", "UTF-8"); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES) .until(() -> getHttpResponse("/lorem.txt").contains("Lorem ipsum")); // Update the resource FileUtils.write(source, uuid, "UTF-8"); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES) .until(() -> getHttpResponse("/lorem.txt").contains(uuid)); // Delete the resource source.delete(); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES) .until(() -> getHttpResponse("/lorem.txt", 404)); } @@ -154,7 +174,7 @@ public void testMultiModuleDevModeWithLocalDepsDisabled() throws MavenInvocation // Wait until we get "uuid" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/app/hello/greeting").contains(uuid)); greeting = getHttpResponse("/app/hello"); @@ -187,12 +207,12 @@ public void testThatTheApplicationIsReloadedOnNewResource() throws MavenInvocati // Wait until we get "bar" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/app/foo").contains("bar")); } @Test - public void testThatClassFileAreCleanedUp() throws MavenInvocationException, IOException { + public void testThatClassFileAreCleanedUp() throws MavenInvocationException, IOException, InterruptedException { testDir = initProject("projects/classic", "projects/project-class-file-deletion"); File source = new File(testDir, "src/main/java/org/acme/ClassDeletionResource.java"); @@ -290,7 +310,7 @@ public void testThatTheApplicationIsReloadedOnConfigChange() throws MavenInvocat File source = new File(testDir, "src/main/resources/application.properties"); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .pollInterval(1, TimeUnit.SECONDS) .until(source::isFile); @@ -299,7 +319,7 @@ public void testThatTheApplicationIsReloadedOnConfigChange() throws MavenInvocat // Wait until we get "uuid" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES) .until(() -> getHttpResponse("/app/hello/greeting").contains(uuid)); } @@ -328,13 +348,13 @@ public void testThatAddingConfigFileWorksCorrectly() throws MavenInvocationExcep "greeting=" + uuid, "UTF-8"); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .pollInterval(1, TimeUnit.SECONDS) .until(configurationFile::isFile); // Wait until we get "uuid" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(10, TimeUnit.SECONDS) .until(() -> getHttpResponse("/app/hello/greeting").contains(uuid)); } @@ -351,7 +371,7 @@ public void testThatExternalConfigOverridesConfigInJar() throws MavenInvocationE "greeting=" + uuid, "UTF-8"); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .pollInterval(1, TimeUnit.SECONDS) .until(configurationFile::isFile); @@ -359,7 +379,7 @@ public void testThatExternalConfigOverridesConfigInJar() throws MavenInvocationE // Wait until we get "uuid" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(60, TimeUnit.SECONDS) .until(() -> getHttpResponse("/app/hello/greeting").contains(uuid)); } @@ -375,7 +395,7 @@ public void testThatNewResourcesAreServed() throws MavenInvocationException, IOE "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", "UTF-8"); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES) .until(() -> getHttpResponse("/lorem.txt").contains("Lorem ipsum")); @@ -383,14 +403,14 @@ public void testThatNewResourcesAreServed() throws MavenInvocationException, IOE String uuid = UUID.randomUUID().toString(); FileUtils.write(source, uuid, "UTF-8"); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES) .until(() -> getHttpResponse("/lorem.txt").contains(uuid)); // Delete the resource source.delete(); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES) .until(() -> getHttpResponse("/lorem.txt", 404)); } @@ -408,7 +428,7 @@ public void testThatApplicationRecoversCompilationIssue() throws MavenInvocation // Wait until we get "uuid" AtomicReference last = new AtomicReference<>(); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> { String content = getHttpResponse("/app/hello", true); last.set(content); @@ -420,14 +440,14 @@ public void testThatApplicationRecoversCompilationIssue() throws MavenInvocation .containsIgnoringCase("compile"); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .pollInterval(1, TimeUnit.SECONDS) .until(source::isFile); filter(source, ImmutableMap.of("\"" + uuid + "\"", "\"carambar\";")); // Wait until we get "uuid" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/app/hello").contains("carambar")); } @@ -443,7 +463,7 @@ public void testThatApplicationRecoversStartupIssue() throws MavenInvocationExce // Wait until we get the error page AtomicReference last = new AtomicReference<>(); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> { String content = getHttpResponse("/app/hello", true); last.set(content); @@ -455,7 +475,7 @@ public void testThatApplicationRecoversStartupIssue() throws MavenInvocationExce filter(source, ImmutableMap.of("class HelloResource", "public class HelloResource")); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> { String content = getHttpResponse("/app/hello", true); last.set(content); @@ -492,18 +512,18 @@ public void testThatNewBeanAreDiscovered() throws IOException, MavenInvocationEx // Wait until we get "uuid" await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/app/hello").contains("message")); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .pollInterval(1, TimeUnit.SECONDS) .until(source::isFile); filter(source, ImmutableMap.of("message", "foobarbaz")); await() - .pollDelay(1, TimeUnit.SECONDS) + .pollDelay(100, TimeUnit.MILLISECONDS) .atMost(1, TimeUnit.MINUTES).until(() -> getHttpResponse("/app/hello").contains("foobarbaz")); }