Any specific requirements for extensions?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Any specific requirements for extensions?

Michael Osipov-2
Folks,

I am trying to write an extension for Maven Resolver which shall replace
a default implementation. The implemented interface is an exported
package in maven-core, the implementing class has proper javax.inject
annotations @Named(...) and @Singleton so does the default (bundled)
one. Put in lib/ext as well as to .mvn/extensions.xml. At no case the
new implementation is picked up by Maven Resolver. Sisu descriptor has
been created also.

Is there anything I have missed? Does it require rather Plexus annotations?

Michael

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Any specific requirements for extensions?

Stuart McCulloch
JSR330 annotation scanning is enabled for all realms including
extensions, so it should be picked up.

Does the replacement implementation have the same "hint" or name?
ie. @Named("default")

You can turn on detailed container logging with -Dsisu.debug which will log
all bindings discovered in each realm/extension and any potential issues.

On Thu, 6 Aug 2020 at 11:45, Michael Osipov <[hidden email]> wrote:

> Folks,
>
> I am trying to write an extension for Maven Resolver which shall replace
> a default implementation. The implemented interface is an exported
> package in maven-core, the implementing class has proper javax.inject
> annotations @Named(...) and @Singleton so does the default (bundled)
> one. Put in lib/ext as well as to .mvn/extensions.xml. At no case the
> new implementation is picked up by Maven Resolver. Sisu descriptor has
> been created also.
>
> Is there anything I have missed? Does it require rather Plexus annotations?
>
> Michael
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Any specific requirements for extensions?

Michael Osipov-2
Am 2020-08-11 um 11:48 schrieb Stuart McCulloch:
> JSR330 annotation scanning is enabled for all realms including
> extensions, so it should be picked up.
>
> Does the replacement implementation have the same "hint" or name?
> ie. @Named("default")
>
> You can turn on detailed container logging with -Dsisu.debug which will log
> all bindings discovered in each realm/extension and any potential issues.

Hi Stuart,

I have followed your advice and added explicit names: "default" for both:

> @Named( "default" )
> @Singleton
> public class DefaultSyncContextFactory
>     implements SyncContextFactory

and

> @Named( "default" )
> @Singleton
> public class RedissonSyncContextFactory
>     implements SyncContextFactory

I can see this:
> 77. LinkedKeyBinding{key=Key[type=java.lang.Object, annotation=*], source=ClassRealm[plexus.core, parent: null], scope=Scopes.NO_SCOPE, target=Key[type=org.eclipse.aether.internal.impl.DefaultSyncContextFactory, annotation=[none]]}
> 78. LinkedKeyBinding{key=Key[type=java.lang.Object, annotation=*], source=ClassRealm[plexus.core, parent: null], scope=Scopes.NO_SCOPE, target=Key[type=org.eclipse.aether.synccontext.RedissonSyncContextFactory, annotation=[none]]}
> 249. ProviderInstanceBinding{key=Key[type=org.eclipse.aether.impl.SyncContextFactory, annotation=[none]], source=org.eclipse.sisu.wire.LocatorWiring, scope=Scopes.NO_SCOPE, provider=org.eclipse.sisu.wire.BeanProviders$7@6cce16f4}
> 334. ConstructorBinding{key=Key[type=org.eclipse.aether.internal.impl.DefaultSyncContextFactory, annotation=[none]], source=ClassRealm[plexus.core, parent: null], scope=Scopes.SINGLETON}
> 335. ConstructorBinding{key=Key[type=org.eclipse.aether.synccontext.RedissonSyncContextFactory, annotation=[none]], source=ClassRealm[plexus.core, parent: null], scope=Scopes.SINGLETON}

I am afraid that the AetherModule as well as DefaultServiceLocator
basically break the bean names, thus making it unusable. The extension
is defitively not picked up because I don't see log statements from it.

Tried also:
> bind( SyncContextFactory.class ).annotatedWith( Names.named( "default" ) ) //
>         .to( DefaultSyncContextFactory.class ).in( Singleton.class );

Even removing did not work.

Changed order in m2.conf, no avail.

Anything else I could try?

Michael

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Any specific requirements for extensions?

Stuart McCulloch
The issue is indeed with AetherModule which is installed by Maven
via MavenAetherModule

This module adds concrete bindings for various Aether components which
cannot be overridden in plugins/extensions.

These bindings will need to be changed to support overriding, I'll create a
patch to show how this could be done.

On Tue, 11 Aug 2020 at 12:07, Michael Osipov <[hidden email]> wrote:

> Am 2020-08-11 um 11:48 schrieb Stuart McCulloch:
> > JSR330 annotation scanning is enabled for all realms including
> > extensions, so it should be picked up.
> >
> > Does the replacement implementation have the same "hint" or name?
> > ie. @Named("default")
> >
> > You can turn on detailed container logging with -Dsisu.debug which will
> log
> > all bindings discovered in each realm/extension and any potential issues.
>
> Hi Stuart,
>
> I have followed your advice and added explicit names: "default" for both:
>
> > @Named( "default" )
> > @Singleton
> > public class DefaultSyncContextFactory
> >     implements SyncContextFactory
>
> and
>
> > @Named( "default" )
> > @Singleton
> > public class RedissonSyncContextFactory
> >     implements SyncContextFactory
>
> I can see this:
> > 77. LinkedKeyBinding{key=Key[type=java.lang.Object, annotation=*],
> source=ClassRealm[plexus.core, parent: null], scope=Scopes.NO_SCOPE,
> target=Key[type=org.eclipse.aether.internal.impl.DefaultSyncContextFactory,
> annotation=[none]]}
> > 78. LinkedKeyBinding{key=Key[type=java.lang.Object, annotation=*],
> source=ClassRealm[plexus.core, parent: null], scope=Scopes.NO_SCOPE,
> target=Key[type=org.eclipse.aether.synccontext.RedissonSyncContextFactory,
> annotation=[none]]}
> > 249.
> ProviderInstanceBinding{key=Key[type=org.eclipse.aether.impl.SyncContextFactory,
> annotation=[none]], source=org.eclipse.sisu.wire.LocatorWiring,
> scope=Scopes.NO_SCOPE,
> provider=org.eclipse.sisu.wire.BeanProviders$7@6cce16f4}
> > 334.
> ConstructorBinding{key=Key[type=org.eclipse.aether.internal.impl.DefaultSyncContextFactory,
> annotation=[none]], source=ClassRealm[plexus.core, parent: null],
> scope=Scopes.SINGLETON}
> > 335.
> ConstructorBinding{key=Key[type=org.eclipse.aether.synccontext.RedissonSyncContextFactory,
> annotation=[none]], source=ClassRealm[plexus.core, parent: null],
> scope=Scopes.SINGLETON}
>
> I am afraid that the AetherModule as well as DefaultServiceLocator
> basically break the bean names, thus making it unusable. The extension
> is defitively not picked up because I don't see log statements from it.
>
> Tried also:
> > bind( SyncContextFactory.class ).annotatedWith( Names.named( "default" )
> ) //
> >         .to( DefaultSyncContextFactory.class ).in( Singleton.class );
>
> Even removing did not work.
>
> Changed order in m2.conf, no avail.
>
> Anything else I could try?
>
> Michael
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Any specific requirements for extensions?

Stuart McCulloch
Scratch that - the AetherModule and DefaultServiceLocator are only used by
clients that don't use dependency injection, they're not used by Maven
itself.

The log snippet you posted above shows both SyncContextFactory components
are being bound in the same realm - they are therefore given the exact same
priority, both being "default", which means the one with the earlier
alphabetical name wins. This is DefaultSyncContextFactory, as shown by its
order in the logs.

Note if the replacement component was bound in a plugin realm then it would
automatically win because the baseline priority is bumped for each plugin
realm added to the system. This is to support Maven's standard behaviour of
always allowing a plugin to override previously bound components. A
component's priority is based on the baseline priority of its realm, with
default components given a boost compared to non-default components. In
other words default components always have a higher priority than
non-default components regardless of the realm/plugin, while components
bound in later plugins have slightly higher priorities than the equivalent
component bound in earlier plugins.

Because the replacement component is bound in the same realm as the
original (since the extension is being pulled into the core realm) then it
has the same baseline priority. So to make sure it appears first you'll
need to explicitly give it a higher priority. You can do this by adding:

    @javax.annotation.Priority(Integer.MAX_VALUE)

to RedissonSyncContextFactory - this will give that component the highest
priority, so it will always appear before any other implementation of that
interface.

On Wed, 12 Aug 2020 at 10:17, Stuart McCulloch <[hidden email]> wrote:

> The issue is indeed with AetherModule which is installed by Maven
> via MavenAetherModule
>
> This module adds concrete bindings for various Aether components which
> cannot be overridden in plugins/extensions.
>
> These bindings will need to be changed to support overriding, I'll create
> a patch to show how this could be done.
>
> On Tue, 11 Aug 2020 at 12:07, Michael Osipov <[hidden email]> wrote:
>
>> Am 2020-08-11 um 11:48 schrieb Stuart McCulloch:
>> > JSR330 annotation scanning is enabled for all realms including
>> > extensions, so it should be picked up.
>> >
>> > Does the replacement implementation have the same "hint" or name?
>> > ie. @Named("default")
>> >
>> > You can turn on detailed container logging with -Dsisu.debug which will
>> log
>> > all bindings discovered in each realm/extension and any potential
>> issues.
>>
>> Hi Stuart,
>>
>> I have followed your advice and added explicit names: "default" for both:
>>
>> > @Named( "default" )
>> > @Singleton
>> > public class DefaultSyncContextFactory
>> >     implements SyncContextFactory
>>
>> and
>>
>> > @Named( "default" )
>> > @Singleton
>> > public class RedissonSyncContextFactory
>> >     implements SyncContextFactory
>>
>> I can see this:
>> > 77. LinkedKeyBinding{key=Key[type=java.lang.Object, annotation=*],
>> source=ClassRealm[plexus.core, parent: null], scope=Scopes.NO_SCOPE,
>> target=Key[type=org.eclipse.aether.internal.impl.DefaultSyncContextFactory,
>> annotation=[none]]}
>> > 78. LinkedKeyBinding{key=Key[type=java.lang.Object, annotation=*],
>> source=ClassRealm[plexus.core, parent: null], scope=Scopes.NO_SCOPE,
>> target=Key[type=org.eclipse.aether.synccontext.RedissonSyncContextFactory,
>> annotation=[none]]}
>> > 249.
>> ProviderInstanceBinding{key=Key[type=org.eclipse.aether.impl.SyncContextFactory,
>> annotation=[none]], source=org.eclipse.sisu.wire.LocatorWiring,
>> scope=Scopes.NO_SCOPE,
>> provider=org.eclipse.sisu.wire.BeanProviders$7@6cce16f4}
>> > 334.
>> ConstructorBinding{key=Key[type=org.eclipse.aether.internal.impl.DefaultSyncContextFactory,
>> annotation=[none]], source=ClassRealm[plexus.core, parent: null],
>> scope=Scopes.SINGLETON}
>> > 335.
>> ConstructorBinding{key=Key[type=org.eclipse.aether.synccontext.RedissonSyncContextFactory,
>> annotation=[none]], source=ClassRealm[plexus.core, parent: null],
>> scope=Scopes.SINGLETON}
>>
>> I am afraid that the AetherModule as well as DefaultServiceLocator
>> basically break the bean names, thus making it unusable. The extension
>> is defitively not picked up because I don't see log statements from it.
>>
>> Tried also:
>> > bind( SyncContextFactory.class ).annotatedWith( Names.named( "default"
>> ) ) //
>> >         .to( DefaultSyncContextFactory.class ).in( Singleton.class );
>>
>> Even removing did not work.
>>
>> Changed order in m2.conf, no avail.
>>
>> Anything else I could try?
>>
>> Michael
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>>
Reply | Threaded
Open this post in threaded view
|

Re: Any specific requirements for extensions?

Michael Osipov-2
Stuart,

that was very valuable information! Thank you!

I have boldly applied your recommendation and it works in the core
realm:
https://github.com/apache/maven-resolver/commit/2e78944a673ac7267f9d40abdeb4816f00381797#diff-0b6e1366069deb9a8dcbf0126334e47dR65-R69

As for the plugin, I have stumbled upon a very interesting case which
broke my entire approach. I tried my code on windup which uses
furnace-maven-plugin. It never picked up my factory. It turned out -- as
you have said -- that specific plugin uses ServiceLocator wrapped in a
MavenContainer class. Even worse, it creates new instances upon every
new mojo call. Completely breaking @Singleton and Maven extremely fast
hits an OOME. When I moved to your solution the plugin used DefaultSCF
again because it does not use injection and but lost the features of my
factory.
To prove that I have added another commit which exists TCCL, CCL and
instance pointers:
https://github.com/apache/maven-resolver/commit/5f001288b036d1e161976bc4450865b5a535f311

Maven itselfs retains the same singleton object at all times, the
furnace-maven-plugin ignores -- for obvious reasons -- @Singleton.
Here is my complete trace file at your convenience:
http://home.apache.org/~michaelo/maven-resolver-redisson/out.txt

Search for
> ExecutionEventLogger - --- furnace-maven-plugin:2.28.4.Final:<goal> (deploy-addons-for-bootstrap-tests) @ windup-tests ---

followed by

> 104934 [BuilderThread 8] [TRACE] DefaultSyncContextFactory - Instance: org.eclipse.aether.internal.impl.DefaultSyncContextFactory@285c4fd, identity: 2041416495

I wonder why Sisu's debug output does not log the priority on created
objects :-(

Thank you very much again!

Michael


Am 2020-08-12 um 11:56 schrieb Stuart McCulloch:

> Scratch that - the AetherModule and DefaultServiceLocator are only used by
> clients that don't use dependency injection, they're not used by Maven
> itself.
>
> The log snippet you posted above shows both SyncContextFactory components
> are being bound in the same realm - they are therefore given the exact same
> priority, both being "default", which means the one with the earlier
> alphabetical name wins. This is DefaultSyncContextFactory, as shown by its
> order in the logs.
>
> Note if the replacement component was bound in a plugin realm then it would
> automatically win because the baseline priority is bumped for each plugin
> realm added to the system. This is to support Maven's standard behaviour of
> always allowing a plugin to override previously bound components. A
> component's priority is based on the baseline priority of its realm, with
> default components given a boost compared to non-default components. In
> other words default components always have a higher priority than
> non-default components regardless of the realm/plugin, while components
> bound in later plugins have slightly higher priorities than the equivalent
> component bound in earlier plugins.
>
> Because the replacement component is bound in the same realm as the
> original (since the extension is being pulled into the core realm) then it
> has the same baseline priority. So to make sure it appears first you'll
> need to explicitly give it a higher priority. You can do this by adding:
>
>      @javax.annotation.Priority(Integer.MAX_VALUE)
>
> to RedissonSyncContextFactory - this will give that component the highest
> priority, so it will always appear before any other implementation of that
> interface.
>
> On Wed, 12 Aug 2020 at 10:17, Stuart McCulloch <[hidden email]> wrote:
>
>> The issue is indeed with AetherModule which is installed by Maven
>> via MavenAetherModule
>>
>> This module adds concrete bindings for various Aether components which
>> cannot be overridden in plugins/extensions.
>>
>> These bindings will need to be changed to support overriding, I'll create
>> a patch to show how this could be done.
>>
>> On Tue, 11 Aug 2020 at 12:07, Michael Osipov <[hidden email]> wrote:
>>
>>> Am 2020-08-11 um 11:48 schrieb Stuart McCulloch:
>>>> JSR330 annotation scanning is enabled for all realms including
>>>> extensions, so it should be picked up.
>>>>
>>>> Does the replacement implementation have the same "hint" or name?
>>>> ie. @Named("default")
>>>>
>>>> You can turn on detailed container logging with -Dsisu.debug which will
>>> log
>>>> all bindings discovered in each realm/extension and any potential
>>> issues.
>>>
>>> Hi Stuart,
>>>
>>> I have followed your advice and added explicit names: "default" for both:
>>>
>>>> @Named( "default" )
>>>> @Singleton
>>>> public class DefaultSyncContextFactory
>>>>      implements SyncContextFactory
>>>
>>> and
>>>
>>>> @Named( "default" )
>>>> @Singleton
>>>> public class RedissonSyncContextFactory
>>>>      implements SyncContextFactory
>>>
>>> I can see this:
>>>> 77. LinkedKeyBinding{key=Key[type=java.lang.Object, annotation=*],
>>> source=ClassRealm[plexus.core, parent: null], scope=Scopes.NO_SCOPE,
>>> target=Key[type=org.eclipse.aether.internal.impl.DefaultSyncContextFactory,
>>> annotation=[none]]}
>>>> 78. LinkedKeyBinding{key=Key[type=java.lang.Object, annotation=*],
>>> source=ClassRealm[plexus.core, parent: null], scope=Scopes.NO_SCOPE,
>>> target=Key[type=org.eclipse.aether.synccontext.RedissonSyncContextFactory,
>>> annotation=[none]]}
>>>> 249.
>>> ProviderInstanceBinding{key=Key[type=org.eclipse.aether.impl.SyncContextFactory,
>>> annotation=[none]], source=org.eclipse.sisu.wire.LocatorWiring,
>>> scope=Scopes.NO_SCOPE,
>>> provider=org.eclipse.sisu.wire.BeanProviders$7@6cce16f4}
>>>> 334.
>>> ConstructorBinding{key=Key[type=org.eclipse.aether.internal.impl.DefaultSyncContextFactory,
>>> annotation=[none]], source=ClassRealm[plexus.core, parent: null],
>>> scope=Scopes.SINGLETON}
>>>> 335.
>>> ConstructorBinding{key=Key[type=org.eclipse.aether.synccontext.RedissonSyncContextFactory,
>>> annotation=[none]], source=ClassRealm[plexus.core, parent: null],
>>> scope=Scopes.SINGLETON}
>>>
>>> I am afraid that the AetherModule as well as DefaultServiceLocator
>>> basically break the bean names, thus making it unusable. The extension
>>> is defitively not picked up because I don't see log statements from it.
>>>
>>> Tried also:
>>>> bind( SyncContextFactory.class ).annotatedWith( Names.named( "default"
>>> ) ) //
>>>>          .to( DefaultSyncContextFactory.class ).in( Singleton.class );
>>>
>>> Even removing did not work.
>>>
>>> Changed order in m2.conf, no avail.
>>>
>>> Anything else I could try?
>>>
>>> Michael
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]