------ Examples ------ Dan Fabulich ------ 2008-08-15 ------ ~~ Licensed to the Apache Software Foundation (ASF) under one ~~ or more contributor license agreements. See the NOTICE file ~~ distributed with this work for additional information ~~ regarding copyright ownership. The ASF licenses this file ~~ to you 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. Examples * Example reactor project Consider an ordinary multi-module reactor build: +---+ my-root-project |-- pom.xml |-- fooUI | `-- pom.xml |-- barBusinessLogic | `-- pom.xml `-- bazDataAccess `-- pom.xml +---+ Suppose project "fooUI" depends on project "barBusinessLogic", which depends on project "bazDataAccess". +---+ fooUI --> barBusinessLogic --> bazDataAccess +---+ Ordinarily, when you run <<>> from <<>>, you'll first build bazDataAccess, then barBusinessLogic, then fooUI. * Resuming the build with reactor:resume Suppose you're working on your code and you attempt to build your code with <<>> from <<>>, and suppose you get a test failure in barBusinessLogic. You make additional changes to barBusinessLogic without changing bazDataAccess; you know that bazDataAccess is fine, so there's no need to rebuild/test it. You can then use <<>>, like this: +---+ mvn reactor:resume -Dfrom=barBusinessLogic +---+ That will skip over bazDataAccess and pick up the build where you left off in barBusinessLogic. If barBusinessLogic succeeds, it will go on to build fooUI. * Making barBusinessLogic without building fooUI using reactor:make Suppose you're a developer working on barBusinessLogic; you don't want to work on fooUI right now, but just want to get a working build of barBusinessLogic. You can use <<>>, like this: +---+ mvn reactor:make -Dmake.folders=barBusinessLogic +---+ <<>> will examine barBusinessLogic and walk down its dependency tree, finding all of the projects that it needs to build. In this case, it will automatically build bazDataAccess and then barBusinessLogic, without building fooUI. * Changing barBusinessLogic and verifying you didn't break anything using reactor:make-dependents Suppose you've made a change to barBusinessLogic; you want to make sure you didn't break any of the projects that depend on you. (In this case, you want to make sure that you didn't break fooUI, but in a more complex reactor that might not be so obvious.) You also want to avoid rebuilding/testing projects that you know you haven't changed. In this case, you want to avoid building bazDataAccess. You can use <<>>, like this: +---+ mvn reactor:make-dependents -Dmake.folders=barBusinessLogic +---+ <<>> will examine all of the projects in your reactor to find projects that depend on barBusinessLogic, and automatically build those and nothing else. In this case, it will automatically build barBusinessLogic and then fooUI. * Building anything that you personally have changed using reactor:make-scm-changes Suppose you've made a change to some source files in barBusinessLogic but you've forgotten what you've changed. You want to make sure you're safe to check-in, and that you haven't broken any projects that depend on you. You can use <<>>, like this: +---+ mvn reactor:make-scm-changes +---+ <<>> determines which files have changed using your SCM (Source Configuration Management) tool, e.g. Subversion, Perforce, Git, etc. To use it, you'll need to configure an SCM connection in your root project POM file: +---+ ... scm:svn:http://svn.mycompany.com/trunk/blah http://svn.mycompany.com/trunk/blah ... +---+ The reactor plugin will use Maven's built-in SCM providers to attempt to figure out which files you've modified. (By default, it will ignore "unknown" files: files that have been created in a source directory but which haven't been explicitly added to source control.) Once the reactor plugin computes the list of changed files, it will figure out which of those files correspond to which projects in the reactor, and basically do a <<>> on those projects that contain changed files. In this example, if you only modified files in barBusinessLogic, then running <<>> is equivalent to running <<>> -- it builds barBusinessLogic and anything that depends on barBusinessLogic (in this case, it will build fooUI). <> with <<<--debug>>> or <<<-X>>> like this: +---+ mvn reactor:make-scm-changes -X +---+ You'll see a log of all the changed files and a depiction of how we computed which projects to pass to <<>>. * Doing a "dry run" with the reactor plugin All of the reactor plugin goals take in an argument <<<-Dmake.printOnly>>> that you can use to see what the goal would have done without actually doing it. For example: +---+ > mvn reactor:make -Dmake.folders=barBusinesslogic -Dmake.printOnly [INFO] Scanning for projects... [...] [INFO] [reactor:make] [INFO] Executing: /Users/danfabulich/svn/redfin/buildtools/maven/bin/mvn -B -N -r -D maven.reactor.includes=bazDataAcecss/pom.xml,barBusinessLogic/pom.xml install [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ +---+ * Running a different goal/lifecycle ("test", "package", "eclipse:eclipse", "clean", etc.) By default, all of the reactor plugin goals will run <<>> on the appropriate projects. That's a pretty reasonable default, but sometimes you want to run a different command on a bunch of projects. All of the reactor plugin goals will accept a <<<-Dmake.goals>>> argument that will let you run other goals instead. You can separate multiple goals with commas: +---+ mvn reactor:make -Dmake.folders=barBusinessLogic -Dmake.goals=eclipse:eclipse mvn reactor:make-dependents -Dmake.folders=barBusinessLogic -Dmake.goals=package,clean mvn reactor:resume -Dmake.folders=barBusinessLogic -Dmake.goals=test +---+ * Skipping tests and passing flags to the spawned Maven The reactor plugin launches a second copy of Maven to do its magic. This copy of Maven doesn't necessarily have all of the flags and options that you passed to your first copy of Maven, including the --debug flag, system properties, and -DskipTests. You can pass additional arguments to the spawned Maven by treating them as goals with <<<-Dmake.goals>>>, like this: +---+ mvn reactor:resume -Dmake.folders=barBusinessLogic -Dmake.goals=install,-DskipTests +---+ In other words, the "goals" are just extra command-line parameters passed to the spawned Maven; they don't necessarily have to be "goals." If you want to get really fancy, you may prefer to just dry run the reactor plugin in <<<-Dmake.printOnly>>> mode, described above. That will print out the command that the plugin would have used to build, but you can tweak that command line to your heart's content! * Resuming a "make" build When you use <<>>, you run a subset of projects, but that doesn't mean stuff won't fail halfway through the build. You can resume a <<>> build from the project that stopped the build by passing <<<-Dfrom>>> to the <<>> goal, like this: +---+ mvn reactor:make -Dmake.folders=fooUI -Dfrom=barBusinessLogic +---+ The <<<-Dfrom>>> argument also works with <<>> and <<>>. * Nested directories Let's consider a more complex project: +---+ my-root-project |-- pom.xml |-- fooUI | `-- pom.xml |-- barBusinessLogic | `-- pom.xml |-- quz | |-- pom.xml | |-- quzAdditionalLogic | | `-- pom.xml | `-- quzUI | `-- pom.xml `-- bazDataAccess `-- pom.xml +---+ Again suppose project "fooUI" depends on project "barBusinessLogic", which depends on project "bazDataAccess". +---+ fooUI --> barBusinessLogic --> bazDataAccess +---+ But furthermore, suppose "quzUI" depends on "quzAdditionalLogic", which depends on "barBusinessLogic." +---+ quzUI --> quzAdditionalLogic --> barBusinessLogic --> bazDataAccess +---+ If you try to run <<>>, you'll get an error: +---+ > mvn reactor:make -Dmake.folders=quzUI [INFO] Folder doesn't exist: /home/person/svn/trunk/quzUI +---+ Naturally, you'll have to specify the complete relative path to quzUI, like this: +---+ > mvn reactor:make -Dmake.folders=quz/quzUI +---+ That would build everything in the reactor except "fooUI". Note that in this project, if you ran <<>> it would build everything in the reactor except bazDataAccess. * Identifying projects by artifact, instead of by folder name Sometimes projects can be nested pretty far down the tree; it can be easier in that case to just identify them by their artifactId instead of by their full relative path. Assuming that the artifactId for "quzUI" is just "quzUI", you can do this: +---+ mvn reactor:make -Dmake.artifacts=com.mycompany:quzUI +---+ or, if you want to resume: +---+ mvn reactor:resume -DfromArtifact=com.mycompany:quzAdditionalLogic +---+ If quzUI has the same groupId as the root POM, you can even omit the "com.mycompany:" groupId and just say: +---+ mvn reactor:make -Dmake.artifacts=quzUI +---+