Skip to content

Commit

Permalink
SHRINKRES-274 Added support for running maven builds as a daemon (#119)
Browse files Browse the repository at this point in the history
It is possible to stop the execution of the main thread and wait till some line matches a regex.  Useful for cases when maven build triggers some server or other application (eg. using mvn spring-boot:run)

The built() method then returns a representation of DaemonBuild - currently, it only returns if the surrounding thread is alive and if not then it can also return an instance of BuiltProject class (as a representation of the built project)
  • Loading branch information
MatousJobanek committed May 18, 2017
1 parent c4ef61e commit e095776
Show file tree
Hide file tree
Showing 29 changed files with 772 additions and 198 deletions.
25 changes: 24 additions & 1 deletion README.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,6 @@ builtProject.getModule(String moduleName)
....
There are several other useful methods provided by this Java class. For more information see link:/maven/api-maven-embedded/src/main/java/org/jboss/shrinkwrap/resolver/api/maven/embedded/BuiltProject.java[BuiltProject]


=== Examples
First example is just package a project and get the default archive:
[source,java]
Expand Down Expand Up @@ -606,6 +605,30 @@ EmbeddedMaven
Some additional examples can be found in integration tests link:/maven/impl-maven-embedded/src/test/java/org/jboss/shrinkwrap/resolver/impl/maven/embedded/pom/equipped[here] and link:/maven/impl-maven-embedded/src/test/java/org/jboss/shrinkwrap/resolver/impl/maven/embedded/invoker/equipped[here].


=== Daemon build
In some cases, you need to run a Maven build in the background. The first case is when the build itself starts some application (eg. `mvn spring-boot:run`). The second case is when you are building a project that is too big so can do some other operation in the meantime let the Maven built run in the background.
In these cases you can specify that the build should be used as a daemon, which means that ShrinkWrap Resolver runs the build in a new separated thread:
[source,java]
....
EmbeddedMaven.forProject("path/to/pom.xml").setGoals("spring-boot:run").useAsDaemon().build();
....
In the case of running some application using the Maven build, it could be useful to wait till the application is started. To do so, use one of the methods:
[source,java]
....
...useAsDaemon().withWaitUntilOutputLineMathes(".*Started Application.*").build();
...useAsDaemon().withWaitUntilOutputLineMathes(".*Started Application.*", 50, TimeUnit.SECONDS).build();
....
In the first case, it waits until some line matches the given regex. If there is no line matched within the default timeout (which is two minutes) then TimeoutException is thrown.
The second case is the same but it sets the timeout to given value.
ShrinkWrap Resolver stops the main thread and waits until some line matches the given regex and then continues. The build itself continues running as well.

In the case you need to build a huge project and let it run on the background and then come back to it later, you can use the object `DaemonBuild` that is returned by the method `build()`:
....
DaemonBuild build = EmbeddedMaven.forProject("path/to/pom.xml").setGoals("package").useAsDaemon().build();
....
This object offers a methods `isAlive()` that says if the thread containing the Maven build is alive or not; and a method `getBuiltProject()` that returns an instance of `BuiltProject` when the thread is not alive, `null` otherwise.


== Experimental features

[WARNING]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,13 @@

package org.jboss.shrinkwrap.resolver.api.maven.embedded;

import org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon.DaemonBuildTrigger;
import org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon.DaemonBuilder;

/**
* @author <a href="mailto:mjobanek@gmail.com">Matous Jobanek</a>
*/
public interface BuildStage {

/**
* Build project using previously configured project data and environment settings.
*
* @return An instance of @{BuiltProject} as a representation of the built project
*/
BuiltProject build();

/**
* If a failure of a project maven build should be ignored. Default is <code>false</code>
*
* @param ignoreFailure If a failure of a project maven build should be ignored
* @return Modified EmbeddedMaven instance
*/
BuildStage ignoreFailure(boolean ignoreFailure);

/**
* Sets that a failure of a project maven build should be ignored.
*
* @return Modified EmbeddedMaven instance
*/
BuildStage ignoreFailure();
public interface BuildStage<DAEMON_TRIGGER_TYPE extends DaemonBuildTrigger>
extends StandardBuilder, DaemonBuilder<DAEMON_TRIGGER_TYPE> {

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@

import java.io.File;
import java.net.URL;
import org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon.DaemonBuildTrigger;

/**
* @author <a href="mailto:mjobanek@gmail.com">Matous Jobanek</a>
*/
public interface DistributionStage<NEXT_STEP extends BuildStage> extends BuildStage{
public interface DistributionStage<NEXT_STEP extends BuildStage<DAEMON_TRIGGER_TYPE>, DAEMON_TRIGGER_TYPE extends DaemonBuildTrigger>
extends BuildStage<DAEMON_TRIGGER_TYPE> {

/**
* Configures EmbeddedMaven to build project with Maven 3 of given version. If the zip file is not cached in directory
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.jboss.shrinkwrap.resolver.api.maven.embedded;

public interface StandardBuilder {

/**
* Build project using previously configured project data and environment settings.
*
* @return An instance of @{BuiltProject} as a representation of the built project
*/
BuiltProject build();

/**
* If a failure of a project maven build should be ignored. Default is <code>false</code>
*
* @param ignoreFailure If a failure of a project maven build should be ignored
* @return Modified EmbeddedMaven instance
*/
StandardBuilder ignoreFailure(boolean ignoreFailure);

/**
* Sets that a failure of a project maven build should be ignored.
*
* @return Modified EmbeddedMaven instance
*/
StandardBuilder ignoreFailure();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon;

import org.jboss.shrinkwrap.resolver.api.maven.embedded.BuiltProject;

/**
* A representation of the daemon Maven build
*/
public interface DaemonBuild {

/**
* Checks if this thread containing the Maven build is alive.
*
* @return <code>true</code> if the thread containing the Maven build is alive;
* <code>false</code> otherwise.
*/
boolean isAlive();

/**
* If the thread containing the Maven build is not alive, then it returns an instance of @{BuiltProject} as a
* representation of the built project; {@code null} otherwise
*
* @return If Maven build is not alive then an instance of @{BuiltProject} as a representation of the built project;
* {@code null} otherwise
*/
BuiltProject getBuiltProject();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon;

public interface DaemonBuildTrigger {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon;

import java.util.concurrent.TimeoutException;

public interface DaemonBuildTriggerWithTimeout extends DaemonBuildTrigger {

/**
* Triggers a build of the project using previously configured project data and environment settings.
*
* @return An instance of {@link DaemonBuild} as a representation of the daemon Maven build.
* @throws TimeoutException if the previously set condition hasn't been met within the set timeout.
*/
DaemonBuild build() throws TimeoutException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon;

public interface DaemonBuildTriggerWithoutTimeout extends DaemonBuildTrigger {

/**
* Triggers a build of the project using previously configured project data and environment settings.
*
* @return An instance of {@link DaemonBuild} as a representation of the daemon Maven build.
*/
DaemonBuild build();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon;

public interface DaemonBuilder<DAEMON_TRIGGER_TYPE extends DaemonBuildTrigger> {

/**
* Ensures that the build of the project will be triggered in separated thread.
*
* @return Instance of some implementation of {@link DaemonBuildTrigger}
*/
DAEMON_TRIGGER_TYPE useAsDaemon();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public interface WithTimeoutDaemonBuilder extends DaemonBuildTriggerWithoutTimeout {

/**
* Resolver will wait until the specified regex matches some line of the build output.
* If the output is not present within two minutes, then {@link TimeoutException} is thrown
*
* @param regex Regex a line of the build output should match
* @return An instance of {@link DaemonBuildTriggerWithTimeout}
*/
DaemonBuildTriggerWithTimeout withWaitUntilOutputLineMathes(String regex);

/**
* Resolver will wait until the specified regex matches some line of the build output.
* If the output is not present within the given time, then {@link TimeoutException} is thrown
*
* @param regex Regex a line of the build output should match
* @param timeout the maximum time to wait
* @param timeoutUnit the time unit of the {@code timeout} argument
* @return An instance of {@link DaemonBuildTriggerWithTimeout}
*/
DaemonBuildTriggerWithTimeout withWaitUntilOutputLineMathes(String regex, long timeout, TimeUnit timeoutUnit);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon;

public interface WithoutTimeoutDaemonBuilder extends DaemonBuildTriggerWithoutTimeout {
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@

import org.jboss.shrinkwrap.resolver.api.maven.embedded.BuildStage;
import org.jboss.shrinkwrap.resolver.api.maven.embedded.DistributionStage;
import org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon.WithoutTimeoutDaemonBuilder;

/**
* @author <a href="mailto:mjobanek@gmail.com">Matous Jobanek</a>
*/
public interface MavenInvokerEquippedEmbeddedMaven extends DistributionStage<BuildStage> {
public interface MavenInvokerEquippedEmbeddedMaven
extends DistributionStage<BuildStage<WithoutTimeoutDaemonBuilder>, WithoutTimeoutDaemonBuilder> {
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package org.jboss.shrinkwrap.resolver.api.maven.embedded.pom.equipped;

import org.jboss.shrinkwrap.resolver.api.maven.embedded.DistributionStage;
import org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon.WithTimeoutDaemonBuilder;

/**
* @author <a href="mailto:mjobanek@redhat.com">Matous Jobanek</a>
*/
public interface ConfigurationDistributionStage
extends ConfigurationStage<ConfigurationDistributionStage>, DistributionStage<ConfigurationStage> {
extends ConfigurationStage<ConfigurationDistributionStage, WithTimeoutDaemonBuilder>,
DistributionStage<ConfigurationStage<ConfigurationDistributionStage, WithTimeoutDaemonBuilder>, WithTimeoutDaemonBuilder> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import org.apache.maven.shared.invoker.InvokerLogger;
import org.jboss.shrinkwrap.resolver.api.maven.embedded.BuildStage;
import org.jboss.shrinkwrap.resolver.api.maven.embedded.BuiltProject;
import org.jboss.shrinkwrap.resolver.api.maven.embedded.daemon.DaemonBuildTrigger;

/**
* @author <a href="mailto:mjobanek@gmail.com">Matous Jobanek</a>
*/
public interface ConfigurationStage<DIST_OR_CONFIG extends ConfigurationStage> extends BuildStage {
public interface ConfigurationStage<DIST_OR_CONFIG extends ConfigurationStage, DAEMON_TRIGGER_TYPE extends DaemonBuildTrigger>
extends BuildStage<DAEMON_TRIGGER_TYPE> {

/**
* Sets the interaction mode of the Maven invocation. Inverse equivalent of -B and --batch-mode
Expand Down
14 changes: 14 additions & 0 deletions maven/impl-maven-embedded/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
<properties>
<version.maven.invoker>2.2</version.maven.invoker>
<version.arquillian.spacelift>1.0.0.Alpha8</version.arquillian.spacelift>
<version.assertj>2.7.0</version.assertj>
<version.awaitility>3.0.0</version.awaitility>
</properties>

<dependencies>
Expand Down Expand Up @@ -63,6 +65,18 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${version.assertj}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>${version.awaitility}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down

0 comments on commit e095776

Please sign in to comment.