Affected version
4.0.0-rc-7; unchanged on master.
Bug description
A mojo written against the Maven 4 API cannot inject a JSR-330/Sisu component from its own plugin realm, although Maven core bridges the two injectors everywhere else.
DefaultMavenPluginManager.loadV4Mojo builds the mojo with a fresh Injector.create() and injector.discover(pluginRealm). discover reads only META-INF/maven/org.apache.maven.api.di.Inject, and the plain InjectorImpl never consults Sisu, so a component listed in the realm's META-INF/sisu/javax.inject.Named cannot be injected into the mojo.
The rest of core does not have this gap. SisuDiBridgeModule.BridgeInjectorImpl falls back to Sisu's BeanLocator for single beans, List and Map, and discoverPluginComponents already installs SisuDiBridgeModule when it scans the plugin realm, so the container does see the component. Only the injector that builds the v4 mojo skips it; the // TODO: get those from the existing plexus scopes ? next to it points at the same spot.
This blocks every Maven 4 API port that uses a library still shipping Sisu components. The ports of maven-scm-publish-plugin, maven-changelog-plugin and maven-release could not inject ScmManager and ended up parsing META-INF/sisu/javax.inject.Named by hand; #13302 lists the same gap for ArchiverManager, VelocityComponent and LocationManager. apache/maven-scm#1418 works around it for maven-scm only.
Reproducer
A maven-core test puts a @javax.inject.Named("sisu") @Singleton component and a Maven 4 API mojo that injects it into one plugin realm, checks that the container finds the component, and asks MavenPluginManager.getConfiguredMojo for the mojo. On master it fails with:
org.apache.maven.plugin.PluginContainerException: Unable to lookup Mojo
at org.apache.maven.plugin.internal.DefaultMavenPluginManager.loadV4Mojo(DefaultMavenPluginManager.java:582)
Caused by: org.apache.maven.di.impl.DIException: No binding to construct an instance for key @Named("sisu") SisuComponent. Existing bindings:
- @Named("org.apache.maven.its:v4-sisu-plugin:1.0:inject") InjectingMojo
- @Named("org.apache.maven.its:v4-sisu-plugin:1.0:inject") Mojo
- ArtifactCoordinatesFactory
- ...
Proposed fix
Build the mojo injector as a BridgeInjectorImpl that consults Sisu only for keys it has no binding for. A plain merge, as core's bridge does, is not enough: Sisu beans always rank above the injector's own bindings, so the Project, MojoExecution and Log that MojoExecutionScopeModule binds in every plugin realm would replace the instances loadV4Mojo binds, and fail with Cannot access Project outside of a scoping block outside a mojo execution scope. A PR with the test follows. #12576 changes the same lines of loadV4Mojo.
Affected version
4.0.0-rc-7; unchanged on
master.Bug description
A mojo written against the Maven 4 API cannot inject a JSR-330/Sisu component from its own plugin realm, although Maven core bridges the two injectors everywhere else.
DefaultMavenPluginManager.loadV4Mojobuilds the mojo with a freshInjector.create()andinjector.discover(pluginRealm).discoverreads onlyMETA-INF/maven/org.apache.maven.api.di.Inject, and the plainInjectorImplnever consults Sisu, so a component listed in the realm'sMETA-INF/sisu/javax.inject.Namedcannot be injected into the mojo.The rest of core does not have this gap.
SisuDiBridgeModule.BridgeInjectorImplfalls back to Sisu'sBeanLocatorfor single beans,ListandMap, anddiscoverPluginComponentsalready installsSisuDiBridgeModulewhen it scans the plugin realm, so the container does see the component. Only the injector that builds the v4 mojo skips it; the// TODO: get those from the existing plexus scopes ?next to it points at the same spot.This blocks every Maven 4 API port that uses a library still shipping Sisu components. The ports of maven-scm-publish-plugin, maven-changelog-plugin and maven-release could not inject
ScmManagerand ended up parsingMETA-INF/sisu/javax.inject.Namedby hand; #13302 lists the same gap forArchiverManager,VelocityComponentandLocationManager. apache/maven-scm#1418 works around it for maven-scm only.Reproducer
A maven-core test puts a
@javax.inject.Named("sisu") @Singletoncomponent and a Maven 4 API mojo that injects it into one plugin realm, checks that the container finds the component, and asksMavenPluginManager.getConfiguredMojofor the mojo. Onmasterit fails with:Proposed fix
Build the mojo injector as a
BridgeInjectorImplthat consults Sisu only for keys it has no binding for. A plain merge, as core's bridge does, is not enough: Sisu beans always rank above the injector's own bindings, so theProject,MojoExecutionandLogthatMojoExecutionScopeModulebinds in every plugin realm would replace the instancesloadV4Mojobinds, and fail withCannot access Project outside of a scoping blockoutside a mojo execution scope. A PR with the test follows. #12576 changes the same lines ofloadV4Mojo.