Skip to content

Conversation

@gnodet
Copy link
Contributor

@gnodet gnodet commented Sep 8, 2025

Summary

Why

  • In some cases, field injection via @Inject failed for services that were retrievable via Session#getService, causing an inconsistency for Maven 4 plugins
  • Plugin authors and core developers need an easy way to run tests with a real session when mocks are not sufficient (e.g., for settings decryption, toolchains, repository wiring)

What changed (highlights)

  • DI/service exposure
    • Seed all available V4 services into the plugin execution scope so @Inject works for Mojos
    • Expose core services comprehensively to the DI container, and unify discovery across Sisu/Guice bridge and internal injector
  • Testing support
    • New @MojoTest(realSession = true) flag to obtain a real session (via ApiRunner) in mojo tests when requested
    • Allow tests to override the session by providing a @provides Session bean (takes precedence over the flag)
  • Integration tests
    • New IT reproducing the problem and validating that @Inject on Mojos works for representative core services

Key implementation details

  • Plugin execution wiring
    • DefaultBuildPluginManager: seed all Session V4 services into the plugin scope for Maven 4 Mojos
    • DefaultMavenPluginManager: bind suppliers for all services into the injector before creating the Mojo instance
  • Service discovery and DI improvements
    • InternalSession + AbstractSession: new getAllServices() returning a map of service interfaces to suppliers; services discovered lazily from the injector to avoid eager creation
    • SisuDiBridgeModule: expose getAllBindings(Class) and improve type-to-key resolution to include Named bindings when no qualifier is present
    • DI injector: add bindSupplier(...) and Binding.toSupplier(...) facilities, plus helper to enumerate bindings
    • DefaultArtifactManager and DefaultProjectManager: explicitly @typed({X.class, Service.class}) so they are exposed as Service implementations discoverable by getAllServices()
  • Session-scoped proxies and @typed semantics
    • SessionScope: when @typed has an empty value, only the class’s direct interfaces are included (not super-interfaces), per project convention; clearer error if @typed is missing
    • Unit tests added to pin this behavior
  • Testing utilities
    • MojoExtension/@MojoTest: optional real session via ApiRunner.createSession() when realSession = true; if creation fails and realSession is true, abort the test with context
    • New SecDispatcherProvider that offers a minimal surface to decrypt settings in tests
  • CI workflow
    • GitHub Actions: use mvn install (instead of verify) in the main job to ensure locally installed artifacts are available to ITs

Backward compatibility and risks

  • Public Maven 4 plugin developer experience improves: @Inject for services in Mojos now matches Session#getService availability
  • InternalSession adds a new method (getAllServices); this is internal to Maven’s impl module and should not affect plugin API compatibility
  • @typed behavior is clarified and tested; existing uses that relied on implicit super-interface inclusion may need to specify explicit interfaces in @typed
  • Minimal CI change from verify to install; builds remain fully validated and provide locally installed artifacts for ITs

Tests

How to use (examples)

  • Inject services directly in Maven 4 Mojos:
@Inject
protected ArtifactManager artifactManager;

@Inject
protected DependencyResolver dependencyResolver;
  • Opt into a real session in a mojo test:
    • Annotate your test class with @MojoTest(realSession = true)
    • Or provide your own @provides @singleton Session to override the default/mock behavior

Notes for reviewers

  • The change is intentionally scoped to Maven 4 Mojos (mojoDescriptor.isV4Api()). Legacy Mojos are not affected
  • DI improvements are conservative: suppliers avoid eager creation; the Sisu/Guice bridge only contributes Plexus beans marked accordingly
  • The new testing affordances help plugin authors (and core) validate realistic scenarios (e.g., settings decryption) without introducing compile-time cycles

Follow-ups

  • Optional: add short developer documentation about @MojoTest(realSession = true) and clarifying @typed behavior in SessionScope
  • Optional: add a brief release note for plugin developers about service injection in Maven 4 Mojos

@gnodet gnodet force-pushed the fix/gh-11055-di-it branch 2 times, most recently from d154847 to a4fd04c Compare September 15, 2025 13:05
…ession mojo testing

Highlights
- All services are injectable into mojos
  - Add InternalSession#getAllServices() to expose all DI service suppliers for the session (Map<Class<? extends Service>, Supplier<? extends Service>>)
  - Add Injector#bindSupplier(Class<T>, Supplier<T>) to bind a type directly to a Supplier
  - Adjust DI bootstrap/bindings (Injector/Binding/InjectorImpl, SisuDiBridgeModule) and touch minor call sites to respect the wiring
- Mojos can be easily tested with a real session
  - @MojoTest(realSession=true) supported by MojoExtension; creates a real InternalSession via ApiRunner, otherwise uses SessionMock
  - New MojoRealSessionTest covers default/custom mock vs real-session paths

Details
- SessionScope alignment: when @typed is empty, include only the class’s direct interfaces (not super-interfaces)
- Testing support: SecDispatcherProvider for encrypted password handling without Sonatype dispatcher; expanded MojoTest for evaluator coverage
- IT: add apachegh-11055-di-service-injection verifying DI service injection end-to-end with pre-populated resources under its/core-it-suite; integrated into TestSuiteOrdering
@gnodet gnodet changed the title Fix/gh 11055 di it Inject all services into mojos and enable easy real-session mojo testing #11055 Sep 15, 2025
@gnodet gnodet added bug Something isn't working backport-to-4.0.x labels Sep 17, 2025
@gnodet gnodet changed the title Inject all services into mojos and enable easy real-session mojo testing #11055 Inject core services directly into Maven 4 Mojos; add opt-in real-session testing (#11055) Sep 17, 2025
@gnodet gnodet merged commit 6b7c9f2 into apache:master Sep 17, 2025
35 of 38 checks passed
@github-actions github-actions bot added this to the 4.1.0 milestone Sep 17, 2025
gnodet added a commit to gnodet/maven that referenced this pull request Sep 17, 2025
…ession mojo testing (apache#11103)

Highlights
- All services are injectable into mojos
  - Add InternalSession#getAllServices() to expose all DI service suppliers for the session (Map<Class<? extends Service>, Supplier<? extends Service>>)
  - Add Injector#bindSupplier(Class<T>, Supplier<T>) to bind a type directly to a Supplier
  - Adjust DI bootstrap/bindings (Injector/Binding/InjectorImpl, SisuDiBridgeModule) and touch minor call sites to respect the wiring
- Mojos can be easily tested with a real session
  - @MojoTest(realSession=true) supported by MojoExtension; creates a real InternalSession via ApiRunner, otherwise uses SessionMock
  - New MojoRealSessionTest covers default/custom mock vs real-session paths

Details
- SessionScope alignment: when @typed is empty, include only the class’s direct interfaces (not super-interfaces)
- Testing support: SecDispatcherProvider for encrypted password handling without Sonatype dispatcher; expanded MojoTest for evaluator coverage
- IT: add apachegh-11055-di-service-injection verifying DI service injection end-to-end with pre-populated resources under its/core-it-suite; integrated into TestSuiteOrdering

(cherry picked from commit 6b7c9f2)
@gnodet
Copy link
Contributor Author

gnodet commented Sep 17, 2025

💚 All backports created successfully

Status Branch Result
maven-4.0.x

Questions ?

Please refer to the Backport tool documentation

gnodet added a commit to gnodet/maven that referenced this pull request Sep 18, 2025
…ession mojo testing (apache#11103)

Highlights
- All services are injectable into mojos
  - Add InternalSession#getAllServices() to expose all DI service suppliers for the session (Map<Class<? extends Service>, Supplier<? extends Service>>)
  - Add Injector#bindSupplier(Class<T>, Supplier<T>) to bind a type directly to a Supplier
  - Adjust DI bootstrap/bindings (Injector/Binding/InjectorImpl, SisuDiBridgeModule) and touch minor call sites to respect the wiring
- Mojos can be easily tested with a real session
  - @MojoTest(realSession=true) supported by MojoExtension; creates a real InternalSession via ApiRunner, otherwise uses SessionMock
  - New MojoRealSessionTest covers default/custom mock vs real-session paths

Details
- SessionScope alignment: when @typed is empty, include only the class’s direct interfaces (not super-interfaces)
- Testing support: SecDispatcherProvider for encrypted password handling without Sonatype dispatcher; expanded MojoTest for evaluator coverage
- IT: add apachegh-11055-di-service-injection verifying DI service injection end-to-end with pre-populated resources under its/core-it-suite; integrated into TestSuiteOrdering

(cherry picked from commit 6b7c9f2)
gnodet added a commit that referenced this pull request Sep 22, 2025
… mojo testing (#11103) (#11139)

Highlights
- All services are injectable into mojos
  - Add InternalSession#getAllServices() to expose all DI service suppliers for the session (Map<Class<? extends Service>, Supplier<? extends Service>>)
  - Add Injector#bindSupplier(Class<T>, Supplier<T>) to bind a type directly to a Supplier
  - Adjust DI bootstrap/bindings (Injector/Binding/InjectorImpl, SisuDiBridgeModule) and touch minor call sites to respect the wiring
- Mojos can be easily tested with a real session
  - @MojoTest(realSession=true) supported by MojoExtension; creates a real InternalSession via ApiRunner, otherwise uses SessionMock
  - New MojoRealSessionTest covers default/custom mock vs real-session paths

Details
- SessionScope alignment: when @typed is empty, include only the class’s direct interfaces (not super-interfaces)
- Testing support: SecDispatcherProvider for encrypted password handling without Sonatype dispatcher; expanded MojoTest for evaluator coverage
- IT: add gh-11055-di-service-injection verifying DI service injection end-to-end with pre-populated resources under its/core-it-suite; integrated into TestSuiteOrdering

(cherry picked from commit 6b7c9f2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-to-4.0.x bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Maven 4: Obtaining services appears to be inconsistent between unit tests and production.

1 participant