Is there any difference between
C:/dev/path/to/Project> mvn package -pl MyModule -am -s settings.xml
and
C:/dev/path/to/Project/MyModule> mvn package -am -s ../settings.xml
As far as I'm concerned, the result of these two actions should be he same.
However, the behaviour seems to be different in each case: the former one seems to be more extensive; the latter ends more quickly - and I'm trying to understand why is that.
a maven module is like a maven "sub-project". a maven project includes 1 or more modules. more info here. Typically, a module generates a single artifact (jar, war, zip, etc), although this is not always true.
In Maven, there are two kinds of plugins, build and reporting: Build plugins are executed during the build and configured in the <build/> element. Reporting plugins are executed during the site generation and configured in the <reporting/> element.
There are 3 types of maven repository: Local Repository. Central Repository. Remote Repository.
Let's first clarify something about multi-module (aggregator) build (that is, invoking the build from the aggregator/parent project) and building a single module.
Let's use the following example:
-+ modules-project
|- module-a
|- module-b (depends on module-a)
Hence modules-project will have as part of its pom the following:
<modules>
<module>module-a</module>
<module>module-b</module>
</modules>
When building from the module-project folder:
module-project> mvn clean install
The Maven Reactor will create the dependency graph of the declared modules and build them accordingly, hence module-a will be built before module-b because module-b depends on module-a
module-b> mvn clean install
Would work correctly, only building module-b, resolving module-a as a dependency (which we installed previously) and using it as part of the build classpath where required.
If instead of invoking a clean install
on modules-project we would have invoked a clean package
, Maven would not have installed anything in our local Maven cache, hence the dependency to module-a in the module-b project could not be resolved. To clarify:
module-project> mvn clean package
Will still build the whole project (with all of its submodules) and create the packages (that is, the jar files).
module-b> mvn clean package
Would now fail, because the dependency to module-a is not present in the local Maven cache nor in any Maven repository, that is, it doesn't exist as a dependency and Maven doesn't know anything about other modules, it is building a simple project (a module) without any knowledge about other modules (as provided by modules-project). When building modules-project instead, Maven is building each module with much more information, knowing that a module has a dependency to another module it will not look on the local cache or on any Maven repository for inter-modules dependencies. Again, it's a reactor build.
That's why you can build a sub-module as a separate build only if you already built the whole multi-module project and installed its artifacts at least in the local Maven cache. And that's why the best practice is always to work from the multi-module project, so that Maven has all the required information and you could:
mvn clean install
)-pl
option (but still starting from the multi-module project)-pl
and -am
options (still from the multi-module project)Let's clarify now the last point, which will also answer your question.
modules-project> mvn clean package -pl module-a
Would run fine, building only module-a as part of the reactor build. However
modules-project> mvn clean package -pl module-b
Would fail, because Maven will try as requested to build module-b, but, again, would look for module-a as a dependency and not a module, hence in the local Maven cache or in the configured Maven repository, not finding it.
modules-project> mvn clean package -pl module-b -am
Would eventually work fine, because now Maven is also building the dependent modules (thanks to -am
) and knows exactly where to find them (as part of the multi-module information, that is, the modules
section).
Let's look at a last case:
module-b> mvn clean package -am
Would fail if we never installed the whole multi-module project (i.e. we always run clean package
), the -am
option would be ignored if not part of a reactor build (because it is an option of the reactor, not of the normal build) and Maven would still try to find module-a in local cache or in repositories.
That's why you should always build a sub-module from its aggregator/parent and via the -pl
and -am
options, to make sure that:
That's also why your observation is right, the first invocation you mentioned (building a submodule from the aggregator project) takes slightly longer because it is not simply the build of a submodule but something more (because there are more information to process and it is a different type of build, a reactor one, potentially building dependent modules also), while building directly a submodule (from its directory) is a simpler Maven build and as such also quicker (but more error prone because of the lack of some information).
More information on these options for a reactor build could be found at:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With