Hi all,
It would be great to get any thoughts on whether the following is a defect:
Issue details:
tl;dr
Maven can resolve dependencies either from:
* an external repo
* a class directory of a module being built within the reactor
* a packaged jar of a module being built within the reactor
If you run a concurrent multi-module build it is possible to get a race
condition whereby the build of module Foo may resolve module Bar from either of
the three resolution channels. This inconsistency can result in the Maven war
plugin sometimes failing to build a functional war file. I would expect a
consistent resolution would always take place.
Full details
Scenario
Consider you have a repo with the following structure:
App
/ \
/ \
(compile scope) (test scope)
/ \
\/_ _\/
ModuleA TestSupportModule1
/
/
(compile scope)
/
\/_
ModuleB
/
/
(test scope)
/
\/_
TestSupportModule2
If you were to make a src code change to the following test support modules:
* TestSupportModule1
* TestSupportModule2
Then the minimum number of modules we need to build to verify the change set is
OK is:
* TestSupportModule1
* TestSupportModule2
* ModuleB
* App
i.e. there is no requirement to build ModuleA because we know that none of the
src code changes could impact the classpaths used in its maven build.
We know that despite 'App' depending (transitively) on ModuleB there is no need
for the 'App' build to wait for ModuleB to complete its build because the src
code change to TestSupportModule2 will not impact any of the classpaths used in
the App maven build. Therefore to get the most efficient build possible we
ideally would invoke Maven to run with 2 threads and with instruction to build
two distinct 'dependency graphs':
* TestSupportModule1 followed by ModuleB
* TestSupportModule1 followed by App
The following Maven command achieves exactly what we want because the reactor
build order is based only on the direct (i.e. non-transitive) dependencies of
the modules provided to the reactor in the build command. Therefore the absence
of ModuleA results in two distinct 'dependency graphs':
mvn clean verify -pl TestSupportModule1,TestSupportModule2,ModuleB,App -T 2
Note: In reality the code base I maintain has a very large monobuild with 100s
of modules and this type of build optimisation makes a significant difference
to the speed of our monobuild (we use
https://github.com/gitflow-incremental-builder/gitflow-incremental-builder to
automate the logic of determining which modules to include in the reactor based
on our change set).
Issue
We have encountered an issue in the above scenario because the 'App' build has
a race condition with the ModuleB build which will result in one of the
following three outcomes:
* If the 'App' build starts before the ModuleB build has compiled its src
classes then the 'App' build will resolve ModuleB from the external repo (i.e.
equivalent to ModuleB not being in the reactor at all)
* If the 'App' build starts after ModuleB has compiled its src classes but
before it has packaged these classes into a jar then the 'App' build will
resolve ModuleB's target/classes directory
* If the 'App' build starts after ModuleB has packaged its jar file then
the 'App' build will resolve ModuleB's target/ModuleB.jar file.
In many scenarios this dependency resolution inconsistency doesn't represent a
challenge. However, it does cause an issue in our case because the 'App' POM
has its Maven packaging stanza configured to war and in the scenario where
ModuleB's target/classes directory is resolved by the 'App' then this results
in the resultant 'App' war file being packaged with a completely empty
ModuleB.jar file.
Proposed solution
Ideally we would like the Maven reactor to retain isolation between the two
distinct 'dependency graphs' it constructs at instantiation throughout the
entire Maven build. This would mean, in the simple example above, that the
'App' would always resolves ModuleB from the external repo (regardless of
whether the reactor has built ModuleB or not in a separate 'dependency graph'
in the reactor).
Joseph Leonard
Manager
Alfa
________________________________
e: [email protected] | w:
alfasystems.com<https://www.alfasystems.com>
t: +44 (0)20 7588 1800 | Moor Place, 1 Fore Street Avenue, London, EC2Y 9DT, GB
________________________________
The contents of this communication are not intended to be binding or constitute
any form of offer or acceptance or give rise to any legal obligations on behalf
of the sender or Alfa. The views or opinions expressed represent those of the
author and not necessarily those of Alfa. This email and any attachments are
strictly confidential and are intended solely for use by the individual or
entity to whom it is addressed. If you are not the addressee (or responsible
for delivery of the message to the addressee) you may not copy, forward,
disclose or use any part of the message or its attachments. At present the
integrity of email across the internet cannot be guaranteed and messages sent
via this medium are potentially at risk. All liability is excluded to the
extent permitted by law for any claims arising as a result of the use of this
medium to transmit information by or to Alfa or its affiliates.
Alfa Financial Software Ltd
Reg. in England No: 0248 2325