And one more thing.... Migrate off from legacy Plexus XML src/main/resources/META-INF/plexus/components.xml
and use JSR330 instead: - add javax.inject:javax.inject:1 as dependency - annotate your imple with @Singleton/@Named( "default" ) - use sisu-maven-plugin in the build to index annotated classes Thanks all T On Wed, Jun 29, 2022 at 1:05 PM Tamás Cservenák <ta...@cservenak.net> wrote: > Also, if you'd not use oldie EventSpy, but > AbstractMavenLifecycleParticipant instead, you'd gain access to session, > and would become even simpler: > just stick something with specific (to your extension, like G:A) key and > dummy value (Boolean,TRUE) into session. > And then you know: if that key IS PRESENT when init, you was not the first > instance of extension to init. > > T > > On Wed, Jun 29, 2022 at 1:01 PM Tamás Cservenák <ta...@cservenak.net> > wrote: > >> Howdy, >> >> First of all, if you alter the maven classpath, there is not much Maven >> itself can do (as it happens before maven happens). How are conflicting >> classes handled depends on Java, not Maven. >> >> So, I'd really just neglect the use of `maven.ext.class.path` (or adding >> things to lib/ext). Using these you (or user) is tampering with very >> internals, and should be really aware of what is being done. >> >> Hence, I went with the 2nd case, the `.mvn/extensions.xml` and used this >> one: >> <?xml version="1.0" encoding="UTF-8"?> >> <extensions> >> <extension> >> <groupId>org.example</groupId> >> <artifactId>double-core-bindings-override</artifactId> >> <version>1.0</version> >> </extension> >> <extension> >> <groupId>org.example</groupId> >> <artifactId>double-core-bindings-override</artifactId> >> <version>2.0</version> >> </extension> >> </extensions> >> >> And to my biggest surprise, Maven did load both extensions just fine >> (based on file order, if you make it 2.0, then 1.0, it will load in that >> order). >> >> [cstamas@urnebes DoubleCoreBindingsOverride]$ ./mvnw validate >> [INFO] Found MyExtension in realm >> 'coreExtension>org.example:double-core-bindings-override:1.0' >> [INFO] Found MyExtension in realm >> 'coreExtension>org.example:double-core-bindings-override:2.0' >> [INFO] Inside MyExtension#init for extension loaded in realm >> 'coreExtension>org.example:double-core-bindings-override:2.0' >> [INFO] Instantiating MyPluginManager for extension loaded in realm >> 'coreExtension>org.example:double-core-bindings-override:2.0' >> [INFO] Using the MavenPluginManager 'MyPluginManager' from realm ' >> coreExtension>org.example:double-core-bindings-override:2.0' >> [INFO] Inside MyExtension#init for extension loaded in realm >> 'coreExtension>org.example:double-core-bindings-override:1.0' >> [INFO] Using the MavenPluginManager 'MyPluginManager' from realm ' >> coreExtension>org.example:double-core-bindings-override:2.0' >> [INFO] Scanning for projects... >> [INFO] >> [INFO] -------------< org.example:double-core-bindings-override >> >-------------- >> [INFO] Building DoubleCoreBindingsOverride reproducer 2.0 >> [INFO] --------------------------------[ jar >> ]--------------------------------- >> [INFO] >> ------------------------------------------------------------------------ >> [INFO] BUILD SUCCESS >> [INFO] >> ------------------------------------------------------------------------ >> [INFO] Total time: 0.037 s >> [INFO] Finished at: 2022-06-29T12:51:56+02:00 >> [INFO] >> ------------------------------------------------------------------------ >> [cstamas@urnebes DoubleCoreBindingsOverride]$ >> >> === >> >> All in all, to prevent this (obviously user mistake), I'd not think too >> much about it: maybe just create a "known" file during init >> - if file does not exist, write an extension version into it >> - if exists, read its content and if matches extension version, all ok, >> otherwise just explode? >> - delete the file in close (when session ends) >> >> This way you will ensure that IF there was a user mistake (double >> configured your extension w/ different versions), it will not end up in an >> inconsistent build, but the user is forced to fix it? >> You could also just create a file (and neglect version), as if file was >> created during init, your 2nd instance should fail (as it means there are >> more than one instances of your extension present). >> >> >> HTH >> T >> >> >> On Tue, Jun 28, 2022 at 4:31 PM François Guillot < >> francoisguillo...@gmail.com> wrote: >> >>> Hi again >>> >>> I can't go into details because it's a proprietary extension, but we need >>> to change the behaviour of >>> - *DefaultMavenPluginManager*: we need to intercept calls to Mojo#execute >>> so here we proxy the Mojo class that is created from the mojoInterface >>> with >>> some custom stuffs >>> - *DefaultBuildPluginManager*: we decorate the #executeMojo with some >>> custom calls to internal classes of ours >>> >>> For now, all is good. I just realized the overridden components might not >>> come from the expected extension so let's say we are theorizing about >>> some >>> possible future binary breakage. >>> >>> You can find attached a small reproducer: >>> >>> https://drive.google.com/file/d/1M-wfS8E_VgHF6qd1CthkHQuzkYEMqNe1/view?usp=sharing >>> >>> (I could not attach the zip directly to Gmail ...) >>> >>> To reproduce, once unzipped: >>> - ./mvnw clean install => install 1.0 in your local repo >>> - change version to 2.0 in pom.xml >>> - ./mvnw clean install => install 2.0 in your local repo >>> - add ".mvn/extensions.xml" with >>> ---------- >>> <?xml version="1.0" encoding="UTF-8"?> >>> <extensions> >>> <extension> >>> <groupId>org.example</groupId> >>> <artifactId>double-core-bindings-override</artifactId> >>> <version>1.0</version> >>> </extension> >>> </extensions> >>> ---------- >>> - execute ./mvnw validate >>> >>> -Dmaven.ext.class.path=${HOME}/.m2/repository/org/example/double-core-bindings-override/2.0/double-core-bindings-override-2.0.jar >>> >>> You should then see sth like >>> >>> [INFO] Found MyExtension in realm 'maven.ext' >>> [INFO] Found MyExtension in realm >>> 'coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Inside MyExtension#init for extension loaded in realm >>> 'coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Instantiating MyPluginManager for extension loaded in realm >>> 'coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Using the MavenPluginManager 'MyPluginManager' from realm ' >>> coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Inside MyExtension#init for extension loaded in realm 'maven.ext' >>> [INFO] Using the MavenPluginManager 'MyPluginManager' from realm ' >>> coreExtension>org.example:double-core-bindings-override:2.0' >>> >>> The extension from maven.ext (extension version 1.0) is found and >>> injected >>> The extension from extensions.xml (extension version 2.0) is found and >>> injected >>> The #init for the 2.0 extension is called >>> The #init for the 1.0 extension is called (maven.ext) >>> Only the MyPluginManager instance from extension 2.0 is present, even >>> when >>> called from the extension 1.0. >>> >>> I understand why this happens but this is potentially dangerous. >>> I tried various ways to avoid that from happening but failed. >>> Hence my question, is there a better way to declare core overrides than >>> in >>> components.xml ? >>> >>> >>> Also, side question, when I'm changing the META-INF/maven/extension.xml >>> to >>> contain >>> >>> <exportedPackages> >>> <exportedPackage>org.example</exportedPackage> >>> </exportedPackages> >>> >>> Then, the problem 'goes away': >>> [INFO] Found MyExtension in realm >>> 'coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Found MyExtension in realm >>> 'coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Inside MyExtension#init for extension loaded in realm >>> 'coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Instantiating MyPluginManager for extension loaded in realm >>> 'coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Using the MavenPluginManager 'MyPluginManager' from realm ' >>> coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Inside MyExtension#init for extension loaded in realm >>> 'coreExtension>org.example:double-core-bindings-override:2.0' >>> [INFO] Using the MavenPluginManager 'MyPluginManager' from realm ' >>> coreExtension>org.example:double-core-bindings-override:2.0' >>> >>> Can you explain what exactly happens in this case ? >>> Maybe I could leverage that to solve my double application problem ? >>> >>> many thanks, >>> François >>> >>> >>> Le mar. 28 juin 2022 à 13:26, Tamás Cservenák <ta...@cservenak.net> a >>> écrit : >>> >>> > In other words, why do you need to override MavenPluginManager in >>> several >>> > different ways? >>> > (or we just theoretize, about some possible future binary breakage?) >>> > >>> > T >>> > >>> > On Tue, Jun 28, 2022 at 1:12 PM Tamás Cservenák <ta...@cservenak.net> >>> > wrote: >>> > >>> > > Ok, >>> > > >>> > > best would be to create then a reproducer, but have to note: >>> > > while Maven can "protect" (warn) about duplicate/wrong plugin >>> > > declarations, as "lower" we go (and extensions, especially when you >>> throw >>> > > things into lib/ext) are earlier and earlier on the bootstrap of >>> Maven, >>> > and >>> > > it cannot do much there... >>> > > Hence, while Maven tries its best to protect you (users) from >>> mistakes, >>> > it >>> > > cannot always do it, especially when things are just added to >>> > classpath.... >>> > > >>> > > Also, non-backward compatible with your implementation of the Maven >>> > > component (interface) of MavenPluginManager? >>> > > Again, I'd really like to see what happens here, what the extension >>> > intent >>> > > is, not only "reproducer" for "multiple extensions override the same >>> > > component". >>> > > >>> > > Tamas >>> > > >>> > > On Tue, Jun 28, 2022 at 12:32 PM François Guillot < >>> > > francoisguillo...@gmail.com> wrote: >>> > > >>> > >> Hi Tamás, >>> > >> >>> > >> I have one extension (say 'MyExtension'), that declares a binding >>> > override >>> > >> for MavenPluginManager. >>> > >> MyExtension is not supposed to be applied several times per build, >>> and >>> > I'm >>> > >> trying my best to keep only one of them 'active' if that happens. >>> > >> Given there are various ways to declare extensions >>> > ('.mvn/extensions.xml', >>> > >> 'lib/ext' in Maven installation, '-Dmaven.ext.class.path'), the >>> order of >>> > >> applications of extensions, the fact they are not loaded in the same >>> > >> classloader makes it a bit hard to do. >>> > >> But I'm managing that. >>> > >> The only thing I'm not managing 'in code' is controlling which >>> extension >>> > >> wins and overrides the Maven core bindings. >>> > >> >>> > >> I'm thinking ahead if at some point I'm making a non backward >>> compatible >>> > >> change (wrt to my extension code) in my implementation of >>> > >> MavenPluginManager, than I can be in trouble, where the 'chosen' >>> > >> MavenPluginManager implementation will not be compatible with the >>> > 'chosen' >>> > >> MyExtension. >>> > >> >>> > >> I can't share the code of my extension, but I could produce a little >>> > >> reproducer with a noop extension to show you what I mean. >>> > >> >>> > >> Le mar. 28 juin 2022 à 11:45, Tamás Cservenák <ta...@cservenak.net> >>> a >>> > >> écrit : >>> > >> >>> > >> > Howdy, >>> > >> > >>> > >> > I am a bit uncertain if I correctly understand your problem: so >>> you >>> > have >>> > >> > several MavenPluginManager implementations in several extensions, >>> and >>> > >> those >>> > >> > extensions are not compatible with each other? >>> > >> > >>> > >> > Could we step back a little and could you explain what your >>> extension >>> > is >>> > >> > doing? Best if you could show us some sources? >>> > >> > >>> > >> > HTH >>> > >> > Tamas >>> > >> > >>> > >> > >>> > >> > >>> > >> > On Tue, Jun 28, 2022 at 10:18 AM François Guillot < >>> > >> > francoisguillo...@gmail.com> wrote: >>> > >> > >>> > >> > > Hi, >>> > >> > > >>> > >> > > I need to override some default Maven bindings in my custom >>> > extension, >>> > >> > for >>> > >> > > instance "org.apache.maven.plugin.MavenPluginManager" >>> > >> > > >>> > >> > > I'm doing this by providing a "META-INF/plexus/components.xml" >>> in my >>> > >> > > extension's jar with >>> > >> > > << >>> > >> > > >>> > >> > > <?xml version="1.0" encoding="UTF-8"?> >>> > >> > > <component-set> >>> > >> > > <components> >>> > >> > > <component> >>> > >> > > <role>org.apache.maven.plugin.MavenPluginManager</role> >>> > >> > > >>> <implementation>com.acme.MyMavenPluginManager</implementation> >>> > >> > > >>> > >> > > </component> >>> > >> > > </components> >>> > >> > > </component-set> >>> > >> > > >>> > >> > > >> >>> > >> > > >>> > >> > > This works fine, but this has limitations. >>> > >> > > If for some reasons, my extension is applied twice or more to >>> the >>> > >> build, >>> > >> > > then all of these applications will override the Maven core >>> binding. >>> > >> My >>> > >> > > finding is that the last application wins. >>> > >> > > This can be problematic if the user is applying several >>> _versions_ >>> > of >>> > >> my >>> > >> > > extension (probably unknowingly), because the overridden >>> > >> > MavenPluginManager >>> > >> > > might be coming from a version of my extension that is not >>> > compatible >>> > >> > with >>> > >> > > the code in the other one. >>> > >> > > >>> > >> > > Is there a more programmatic way to override Maven core >>> bindings, >>> > that >>> > >> > > would allow me to decide whether a given extension should >>> perform >>> > the >>> > >> > > override or not ? >>> > >> > > >>> > >> > >>> > >> >>> > > >>> > >>> >>