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

Reply via email to