Spike to figure out how to replace the custom Maven parsing with something more solid.
Why does it need to be done?
The parsing of Maven projects is implemented with (naive) custom code that parses trivial and most common Maven projects. But, it has many limitations compared to Maven's parsing capabilities.
Attempting to remove these limitations would require a reimplementation of Maven's parsing logic which is not feasible.
Requirements
Maven's internals need to be accessed to e.g. retrieve the resolved Paths to the jars on the classpath, these can change depending on e.g. profile settings
The internals can be retrieved from MavenSession.
MavenSession is accessible through Maven ExecutionListeners
The ExecutionListeners can be registered on the MavenExecutionRequest
To access the required internals it is required to register an ExecutionListener and retrieve the session when the build is finished.
The PLexusContainer setup and Maven internals are no trivial and a solution should use Maven code whenever possible
Options
Different options exist to execute Maven goals from Java code.
These are the options I am aware of and have looked into:
Allows access to MavenSession, MavenProject, and others and to register ExecutionListeners
Requires the "installation" of a jar on the machine, either in the project META-INF/maven/extension.xml, or (preferably) in a central location ${maven.home}/lib/ext.
The extension would still run in the Maven process and the instances re not accessible form outside
Has a EmbeddedMaven class that allows executing Maven goals. It defines a withMavenInvoker method that takes a org.apache.maven.shared.invoker.InvocationRequest. This code does what's required (it seems)
That was the current approach after the classpath issues in Boot application after using Maven Internals
Not feasable
Maven internals ❌
We had problems when used in a Boot application. The ClassWorld class loading was conflicting with Boot class loading
Probably more complexity to come
Solution
None of the solutions above fulfill the requirements.
But, the MavenCli has everything required to start a Maven build from within the same JVM process.
It hides the access to the MavenExecutionResult.
I created a shameless copy of the MavenCli and provide the listener through this implementation.
This guarantees that the build is as close as possible to what Maven does with the EmbeddedMaven.
WIP
[ ] Check if OpenRewrite's build plugin code can be incorporated as is to reuse as much of their logic as possible.
[x] Solve ClassLoader conflicts with ClassWorld running in a Spring Boot application 🤞
What needs to be done?
Spike to figure out how to replace the custom Maven parsing with something more solid.
Why does it need to be done?
The parsing of Maven projects is implemented with (naive) custom code that parses trivial and most common Maven projects. But, it has many limitations compared to Maven's parsing capabilities. Attempting to remove these limitations would require a reimplementation of Maven's parsing logic which is not feasible.
Requirements
Path
s to the jars on the classpath, these can change depending on e.g. profile settingsMavenSession
.MavenSession
is accessible through MavenExecutionListener
sExecutionListener
s can be registered on theMavenExecutionRequest
ExecutionListener
and retrieve the session when the build is finished.Options
Different options exist to execute Maven goals from Java code. These are the options I am aware of and have looked into:
Invoker
M2_HOME
orMAVEN_HOME
to point to a Maven installMavenCli
.MavenSession
,MavenProject
, and others and to registerExecutionListener
sMETA-INF/maven/extension.xml
, or (preferably) in a central location${maven.home}/lib/ext
.EmbeddedMaven
class that allows executing Maven goals. It defines awithMavenInvoker
method that takes aorg.apache.maven.shared.invoker.InvocationRequest
. This code does what's required (it seems)PropagateExecutionContextMojo
makes me think if the approach could work for the current problem as well.Solution
None of the solutions above fulfill the requirements. But, the
MavenCli
has everything required to start a Maven build from within the same JVM process. It hides the access to theMavenExecutionResult
. I created a shameless copy of theMavenCli
and provide the listener through this implementation. This guarantees that the build is as close as possible to what Maven does with theEmbeddedMaven
.WIP
[ ] Check if OpenRewrite's build plugin code can be incorporated as is to reuse as much of their logic as possible.
[x] Solve ClassLoader conflicts with
ClassWorld
running in a Spring Boot application 🤞