Skip to content

Maven 4 API mojos cannot inject Sisu components from their plugin realm #13326

Description

@slachiewicz

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmvn4

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions