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