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 ? >> > >> > > >> > >> > >> > >> >> > > >> > >> >