Skip to content

Fix #13459: support package-private configuration classes in plugins - #13470

Open
gnodet wants to merge 2 commits into
apache:masterfrom
gnodet:fix/13459-package-private-config-classes
Open

gnodet wants to merge 2 commits into
apache:masterfrom
gnodet:fix/13459-package-private-config-classes

Conversation

@gnodet

@gnodet gnodet commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Problem

AbstractConfigurationConverter.instantiateObject() (from org.eclipse.sisu.plexus) uses Class.newInstance() which requires a public no-arg constructor. This prevents using package-private classes (or static inner classes with non-public constructors) as @Parameter configuration types in Maven 4 API plugins — an IllegalAccessException is thrown at configuration time.

This was discovered while working on removing the maven-archiver dependency from maven-jar-plugin (apache/maven-jar-plugin#618): the plugin's ArchiveConfiguration type would benefit from being a package-private class but currently cannot be used as a @Parameter type.

Fixes #13459.

Solution

EnhancedConfigurationConverter already overrides fromConfiguration(), which is the call site of instantiateObject(). Since instantiateObject is protected final in AbstractConfigurationConverter (from sisu, not overridable), we replace the call with a local instantiate() method that uses:

var ctor = type.getDeclaredConstructor();
if (!ctor.canAccess(null)) {
    ctor.setAccessible(true);
}
return ctor.newInstance();

This is symmetric with how EnhancedCompositeBeanHelper.setFieldValue() already handles non-public fields (via field.setAccessible(true)). The fix makes constructor instantiation consistent with field injection.

Alternative

A one-line fix in eclipse-sisu/sisu.plexus's AbstractConfigurationConverter.instantiateObject() would be the cleanest long-term solution, but that requires a sisu release cycle. This Maven-side fix is immediately actionable.

…hancedConfigurationConverter

The Plexus AbstractConfigurationConverter.instantiateObject() uses
Class.newInstance() which requires a public no-arg constructor.
This prevents using package-private classes (or inner classes) as
@parameter configuration types in Maven 4 API plugins.

EnhancedCompositeBeanHelper.setFieldValue() already handles non-public
fields by calling field.setAccessible(true). This commit makes object
instantiation symmetric: override the call site in
EnhancedConfigurationConverter.fromConfiguration() with a local
instantiate() method that uses getDeclaredConstructor() +
setAccessible(true), consistent with the field injection strategy.

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix is mechanically correct and symmetric with EnhancedCompositeBeanHelper.setFieldValue(). One gap before merge: no test was added to validate the fixed scenario.

Also, please set the milestone to 4.1.0 (issue #13459 targets it).

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@gnodet gnodet added this to the 4.1.0 milestone Oct 13, 2026

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous finding (missing test) is fully addressed. The fix is correct: getDeclaredConstructor() + setAccessible(true) properly handles package-private constructors, and the test validly reproduces the original bug (Class.newInstance() fails because the access check uses AbstractConfigurationConverter as the caller, which is in a different package from PackagePrivateBean).

This review was generated by an AI agent, Hermès on behalf of @gnodet.

gnodet added a commit to gnodet/maven-jar-plugin that referenced this pull request Oct 13, 2026
@gnodet gnodet added bug Something isn't working mvn4 backport-to-4.0.x enhancement New feature or request and removed bug Something isn't working backport-to-4.0.x labels Oct 14, 2026
}
}

private static Object instantiate(Class<?> type, PlexusConfiguration configuration)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with this part of the code, so maybe my remark will be irrelevant. But the instantiateObject method is apparently inherited from the parent class. Maybe this new instantiate method should be added next to it. Then:

  • Check if instantiateObject is still used and, if not, remove it.
  • This pull request said that this change is "symmetric with EnhancedCompositeBeanHelper.setFieldValue". If symmetric, then can the latter method share the new instantiate method introduced by this pull request (if that method can put moved to the parent class)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parent class has a method instantiateObject, but it's protected final.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but protected final method can be used in subclasses. Maybe the same should be done for instantiate.

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

Labels

enhancement New feature or request mvn4

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow package-private @Parameter fields in Maven 4 API plugins

3 participants