Hi Jospeh,

I didn’t necessarily expect that enabling the extension would solve/avoid the 
issue you described, but I mentioned it, because it would allow you to not have 
to specify an argument like '-pl 
TestSupportModule1,TestSupportModule2,ModuleB,App’ in the first place, because 
the Build Cache Extension should automatically determine which modules need to 
be built and for which ones previously cached artifacts can be used.

Nils.

> Op 6 feb 2024, om 15:11 heeft Joseph Leonard <joseph.leon...@alfasystems.com> 
> het volgende geschreven:
> 
> Thanks Nils,
> maven-build-cache-extension looks very interesting generally – I will have a 
> play with it.
> With regards to this issue, the maven-build-cache-extension overview 
> references “Subtree support for multimodule projects builds part of the 
> codebase in isolation” which sounded similar to the solution I am proposing 
> for this issue. Unfortunately, after enabling the maven-build-cache-extension 
> I still hit the same issue.
> Joe
> 
> On 2024/02/06 12:54:59 Nils Breunese wrote:
>> I can’t comment on your question directly, but I just wanted to say that 
>> your use case sounds like it could benefit from the Maven Build Cache 
>> Extension (https://maven.apache.org/extensions/maven-build-cache-extension/).
> 
>> 
>> Just my 2 cents.
>> 
>> Nils.
>> 
>>> Op 6 feb 2024 om 11:40 heeft Joseph Leonard <jo...@alfasystems.com> het 
>>> volgende geschreven:
>>> 
>>> 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: joseph.leon...@alfasystems.com | 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
>> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@maven.apache.org
For additional commands, e-mail: users-h...@maven.apache.org

Reply via email to