As Hervé noted, much of this is the way Maven (and Plexus) has always behaved - the core defines component roles that plugins/extensions can implement. There will typically be a core implementation (sometimes named as the default, but not always) but that implementation can be overridden by implementations in plugins/extensions so people can extend and augment Maven. Sometimes the consumer of a component role wants to see all implementations and will inject a list or a map (keyed by name) - for example handlers of different archive types where you might ship a stock set of handlers, but want to allow plugins to add handlers for other archive types.
So there has always been multiple implementations of a given component role, and an ordering to decide which one to return when someone asks for just one implementation of that role (compared to asking for a list or a map). Historically Plexus always gave implementations in plugins/extensions a slightly higher priority than core - and "newer" plugins in terms of when they were added to the runtime build a slightly higher priority than "older" plugins. The ordering of implementations inside a given realm or classloader followed the "classpath" ordering of the jars, while the ordering of implementations inside a jar followed their order in the Plexus XML descriptor. Almost 10 years ago Maven switched from the old Plexus container to a new shim built on top of Guice that supports the same Plexus API and behaviour. In other words, the same ranking between core and plugin/extension implementations and the same classpath/descriptor ordering for implementations in the same classloader/jar. When moving from Plexus annotations to JSR330 annotations the same behaviour was applied to the order of implementations in the javax.injected.Named descriptor (which is in some ways a replacement for Plexus' components.xml.) The code and behaviour to manage all this has been there for a while since the shim manages both sets of annotations and maps them to Guice bindings, it's only recently that selected parts of Maven have been switching from Plexus annotations to JSR330 annotations. This is why the ordering in the javax.injected.Named descriptor makes a difference in terms of multiple implementations in the same jar - it's following the same historical ordering that Plexus would apply to implementations in components.xml. The difference is that the javax.injected.Named descriptor is typically built as the code is compiled by using an annotation processor, rather than as a separate packaging step (although that can be configured when it makes sense such as generating an uber-index for a collection of archives.) The use of an annotation processor means that differences in the order that javac compiles the classes can currently affect the order of them in the descriptor. A lot of the time that ordering doesn't change, especially when you're using the same OS and version of java, but to make sure we get completely reproducible builds Hervé has proposed a stricter ordering on the javax.injected.Named descriptor. On Sun, 3 Nov 2019 at 04:31, Gabriel Belingueres <[email protected]> wrote: > Thanks Stuart. > > The reproducibility PR you mention helps in having a deterministic ordering > inside the Named components file to buld exactly the same executable, but > it does not mean it is the right priority for component injection. > > Do you know if it is possible to configure sisu to throw an exception if > trying to inject an ambiguous component? Otherwise, I guess we must > implement some sort of "ambiguity checker", either as an integration test > (don't know if it is possible) or either built-it into maven executable. > > > > > El sáb., 2 de nov. de 2019 a la(s) 20:54, Stuart McCulloch ( > [email protected]) escribió: > > > Yes, when there are multiple non-default implementations with the same > > priority then it will pick the first in the list (where the "list" in > > question is actually a combination of plugins + extensions + core > > bindings for the given type) > > > > If a particular implementation should be treated as the default then it > > should either start with "Default" or be annotated with > @Named("default") - > > the benefit of this approach is that it documents that this is the > default > > implementation, to be favoured over the others. Alternatively if you want > > to have an ordering between implementations then you can use @Priority to > > assign specific priorities and favour one over the other. > > > > If you don't mark an implementation as default and don't define any > > priorities then the only current guarantees are that implementations in > > plugins and extensions will be favoured over implementations in core (to > > allow overriding). But there is an upcoming improvement to sort the list > > inside each module that would make this more deterministic from build to > > build, at least when ranking implementations inside a particular module: > > https://github.com/eclipse/sisu.inject/pull/5 - with that change then > > you'll get an extra guarantee that inside a module it will be ordered by > > package+name. > > > > PS. even with the old Plexus runtime annotations you could be at the whim > > of classpath ordering, similarly Plexus XML descriptors are influenced by > > classpath resource ordering - so ideally it's better to be explicit about > > ordering > > > > On Sat, 2 Nov 2019 at 23:07, Gabriel Belingueres <[email protected]> > > wrote: > > > > > Hi: > > > > > > I just built maven core from source and found that it was using > > > StringSearchModelInterpolator instead of > StringVisitorModelInterpolator, > > a > > > regression from the last 3.6.2 release. > > > > > > I found that in maven-model-builder/META-INF/sisu/javax.injected.Named > > > file, both interpolators are listed but in reverse order (comparing it > > with > > > the same file in 3.6.2), that is StringSearchModelInterpolator appear > > first > > > in the file and StringVisitorModelInterpolator second. > > > > > > (I believe the dependency injection picks up the first one it finds > with > > > the right type.) > > > > > > Deleting the @Named annotation from StringSearchModelInterpolator > solved > > > the issue, as this make the entry disappear from the > javax.injected.Named > > > file. Then the dependency injection uses the > > > StringVisitorModelInterpolator. > > > > > > Can anyone confirm this issue? > > > And if so, how to best prevent in the future that this type of > dependency > > > injection regressions from happening? > > > > > > Kind regards, > > > Gabriel > > > > > >
