diff --git a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/.asciidoctorconfig b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/.asciidoctorconfig index b1785c722edc..b195ce90a821 100644 --- a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/.asciidoctorconfig +++ b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/.asciidoctorconfig @@ -1,3 +1,4 @@ // Asciidoctor IDE configuration file. // See https://github.com/asciidoctor/asciidoctor-intellij-plugin/wiki/Support-project-specific-configurations +:experimental: :doc_code: ../../java diff --git a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/maven/jetty-maven-plugin.adoc b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/maven/jetty-maven-plugin.adoc index bebff5200fdc..90fa86d804ef 100644 --- a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/maven/jetty-maven-plugin.adoc +++ b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/maven/jetty-maven-plugin.adoc @@ -55,7 +55,7 @@ We recommend either the traditional link:{DISTGUIDE}[distribution] deployment ap ==== [[get-up-and-running]] -==== Quick Start: Get Up and Running +==== Get Up and Running First, add `jetty-maven-plugin` to your `pom.xml` definition: @@ -77,10 +77,10 @@ mvn jetty:run This starts Jetty and serves up your project on http://localhost:8080/. Jetty will continue to run until you stop it. -By default, it will not automatically restart your webapp: you can force a redeploy by hitting the `Enter` key. -Set a non-zero <scan> value to have jetty scan your webapp for changes and automatically redeploy. +By default, it will not automatically restart your webapp. +Set a non-zero `` value to have jetty scan your webapp for changes and automatically redeploy, or set `` to `0` to cause manual redeployment by hitting the kbd:[Enter] key. -You can terminate the plugin with a `ctrl-c` in the terminal window where it is running. +You can terminate the plugin with a kbd:[Ctrl+c] in the terminal window where it is running. [NOTE] ==== @@ -300,7 +300,7 @@ For example, by default it looks for: * `web.xml` in `${project.basedir}/src/main/webapp/WEB-INF/` The plugin first runs a maven parallel build to ensure that the classes are built and up-to-date before deployment. -If you change the source of a class and your IDE automatically compiles it in the background, the plugin picks up the changed class (note you need to configure a non-zero `scan` interval for automatic redeployment, otherwise redeployment only occurs if you hit the `Enter` key). +If you change the source of a class and your IDE automatically compiles it in the background, the plugin picks up the changed class (note you need to configure a non-zero `scan` interval for automatic redeployment). If the plugin is invoked in a multi-module build, any dependencies that are also in the maven reactor are used from their compiled classes. Prior to jetty-9.4.7 any dependencies needed to be built first. @@ -389,8 +389,9 @@ If true, the classes from `testClassesDirectory` and dependencies of scope "test By default this is false. scan:: The pause in seconds between sweeps of the webapp to check for changes and automatically hot redeploy if any are detected. -*By default this is 0, which disables hot deployment scanning. Redeployment is by hitting `Enter` key.* -A number greater than 0 enables it. +*By default this is `-1`, which disables hot redeployment scanning.* +A value of `0` means no hot redeployment is done, and that you must use the kbd:[Enter] key to manually force a redeploy. +Any positive integer will enable hot redeployment, using the number as the sweep interval in seconds. scanTargetPatterns:: Optional. List of extra directories with glob-style include/excludes patterns (see http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-[javadoc] for http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-[FileSystem.getPathMatcher]) to specify other files to periodically scan for changes. @@ -462,7 +463,6 @@ When invoked at the command line this goal first executes a maven build of your By default it then deploys the resultant war to jetty, but you can use this goal instead to deploy _any_ war file by simply setting the `<webApp><war>` configuration parameter to its location. If you set a non-zero `scan`, Jetty watches your `pom.xml` and the WAR file; if either changes, it redeploys the war. -With a zero `scan` interval, redeployment is manual via hitting the `Enter` key. The maven build is held up until jetty exits, which is achieved by typing `cntrl-c` at the command line. @@ -501,8 +501,9 @@ contextXml::: The path to a context xml file that is applied to your webapp AFTER the `webApp` element. scan:: The pause in seconds between sweeps of the webapp to check for changes and automatically hot redeploy if any are detected. -*By default this is 0, which disables hot deployment scanning. Redeployment is by hitting `Enter` key.* -A number greater than 0 enables it. +*By default this is `-1`, which disables hot redeployment scanning.* +A value of `0` means no hot redeployment is done, and that you must use the kbd:[Enter] key to manually force a redeploy. +Any positive integer will enable hot redeployment, using the number as the sweep interval in seconds. scanTargetPatterns:: Optional. List of directories with ant-style include/excludes patterns to specify other files to periodically scan for changes. @@ -531,7 +532,6 @@ Here's an example of using the `pre-integration-test` and `post-integration-test jetty-maven-plugin {VERSION} - 10 foo 9999 @@ -542,9 +542,6 @@ Here's an example of using the `pre-integration-test` and `post-integration-test start - - 0 - stop-jetty diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java index beb6d3ca9918..5434440c8def 100644 --- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java +++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java @@ -29,7 +29,9 @@ import org.apache.maven.plugins.annotations.ResolutionScope; import org.eclipse.jetty.util.IncludeExcludeSet; import org.eclipse.jetty.util.Scanner; +import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.webapp.WebAppContext; /** @@ -52,14 +54,16 @@ @Execute (phase = LifecyclePhase.TEST_COMPILE) public class JettyRunMojo extends AbstractUnassembledWebAppMojo { - //Start of parameters only valid for runType=inprocess + //Start of parameters only valid for deploymentType=EMBED /** - * The interval in seconds to pause before checking if changes - * have occurred and re-deploying as necessary. A value - * of 0 indicates no re-deployment will be done. In that case, you - * can force redeployment by typing a linefeed character at the command line. + * Controls redeployment of the webapp. + *
    + *
  1. -1 : means no redeployment will be done
  2. + *
  3. 0 : means redeployment only occurs if you hit the ENTER key
  4. + *
  5. otherwise, the interval in seconds to pause before checking and redeploying if necessary
  6. + *
*/ - @Parameter(defaultValue = "0", property = "jetty.scan", required = true) + @Parameter(defaultValue = "-1", property = "jetty.scan", required = true) protected int scan; /** @@ -138,6 +142,12 @@ public void startJettyHome() throws MojoExecutionException private void startScanner() throws Exception { + if (scan < 0) + { + getLog().info("Redeployment not enabled"); + return; //no automatic or manual redeployment + } + // start scanning for changes, or wait for linefeed on stdin if (scan > 0) { @@ -145,8 +155,27 @@ private void startScanner() scanner.setScanInterval(scan); scanner.setScanDepth(Scanner.MAX_SCAN_DEPTH); //always fully walk directory hierarchies scanner.setReportExistingFilesOnStartup(false); + scanner.addListener(new Scanner.BulkListener() + { + public void filesChanged(Set changes) + { + try + { + restartWebApp(changes.contains(project.getFile().getCanonicalPath())); + } + catch (Exception e) + { + getLog().error("Error reconfiguring/restarting webapp after change in watched files", e); + } + } + }); configureScanner(); - getLog().info("Scan interval ms = " + scan); + getLog().info("Scan interval sec = " + scan); + + //unmanage scheduler so it is not stopped with the scanner + Scheduler scheduler = scanner.getBean(Scheduler.class); + scanner.unmanage(scheduler); + LifeCycle.start(scheduler); scanner.start(); } else @@ -184,21 +213,6 @@ protected void configureScanner() { throw new MojoExecutionException("Error forming scan list", e); } - scanner.addListener(new Scanner.BulkListener() - { - public void filesChanged(Set changes) - { - try - { - boolean reconfigure = changes.contains(project.getFile().getCanonicalPath()); - restartWebApp(reconfigure); - } - catch (Exception e) - { - getLog().error("Error reconfiguring/restarting webapp after change in watched files", e); - } - } - }); } public void gatherScannables() throws Exception diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/Scanner.java b/jetty-util/src/main/java/org/eclipse/jetty/util/Scanner.java index 083349cee64f..4a00309ee9bb 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/Scanner.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/Scanner.java @@ -36,7 +36,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; -import org.eclipse.jetty.util.component.AbstractLifeCycle; +import org.eclipse.jetty.util.component.ContainerLifeCycle; import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; import org.eclipse.jetty.util.thread.Scheduler; import org.slf4j.Logger; @@ -48,7 +48,7 @@ * Utility for scanning a directory for added, removed and changed * files and reporting these events via registered Listeners. */ -public class Scanner extends AbstractLifeCycle +public class Scanner extends ContainerLifeCycle { /** * When walking a directory, a depth of 1 ensures that @@ -69,7 +69,7 @@ public class Scanner extends AbstractLifeCycle private boolean _reportExisting = true; private boolean _reportDirs = true; private Scheduler.Task _task; - private Scheduler _scheduler; + private final Scheduler _scheduler; private int _scanDepth = DEFAULT_SCAN_DEPTH; private enum Status @@ -279,9 +279,17 @@ default void scanEnded(int cycle) throws Exception { } } - + public Scanner() { + this(new ScheduledExecutorScheduler("Scanner-" + SCANNER_IDS.getAndIncrement(), true, 1)); + } + + public Scanner(Scheduler scheduler) + { + //Create the scheduler and start it + _scheduler = scheduler; + addBean(_scheduler); } /** @@ -514,10 +522,7 @@ public void doStart() throws Exception _prevScan = scanFiles(); } - - //Create the scheduler and start it - _scheduler = new ScheduledExecutorScheduler("Scanner-" + SCANNER_IDS.getAndIncrement(), true, 1); - _scheduler.start(); + super.doStart(); //schedule the scan schedule(); @@ -539,10 +544,6 @@ public void doStop() throws Exception _task = null; if (task != null) task.cancel(); - Scheduler scheduler = _scheduler; - _scheduler = null; - if (scheduler != null) - scheduler.stop(); } /**