Hi all,

While chasing the rc-6 IntelliJ breakage I ran into something I think deserves 
a separate discussion. The immediate bug is small and already has a fix — 
#13068 <https://github.com/apache/maven/issues/13068> / PR #13069 
<https://github.com/apache/maven/pull/13069>: rc-6 added two abstract methods 
to the internal PluginDependenciesResolver, which breaks out-of-tree 
implementations with AbstractMethodError, and making them default restores 
compatibility.

The trigger was Apache PLC4X becoming unusable in IntelliJ, reported by 
Christofer Dutz on their dev list ("[DISCUSS] Downgrade to maven 4 RC-5?" 
<https://lists.apache.org/thread/pkry4orbrl5nndnocgwzk6l5137tkyzp>), who also 
verified the fix. Guillaume root-caused it in reply to Sergey Chernov's -1 on 
the rc-6 vote 
<https://lists.apache.org/thread/mtt7kg632lfs2hxcx0nv9bn4omkgbvt6>.

The question I would like to raise is why that broke anything at all.

Three IDEs override the same internal component

IDE     Class   How
IntelliJ IDEA   Maven40PluginDependenciesResolver 
<https://github.com/JetBrains/intellij-community/blob/master/plugins/maven/maven40-server-impl/src/com/intellij/maven/server/m40/utils/Maven40PluginDependenciesResolver.java>
        implements the interface, @Priority(10)
Eclipse m2e     EclipsePluginDependenciesResolver 
<https://github.com/eclipse-m2e/m2e-core/blob/main/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/project/registry/EclipsePluginDependenciesResolver.java>
    extends DefaultPluginDependenciesResolver
NetBeans        NbPluginDependenciesResolver 
<https://github.com/apache/netbeans/blob/master/java/maven.embedder/src/org/netbeans/modules/maven/embedder/impl/NbPluginDependenciesResolver.java>
        extends DefaultPluginDependenciesResolver
That is every major Java IDE, independently, on an interface whose javadoc says 
it "can be changed or deleted without prior notice".

Two of the three do it for the identical reason: workspace resolution must not 
apply to plugin resolution. Resolver's WorkspaceReader is session-scoped with 
no plugin-versus-dependency distinction, so the only way to say "resolve 
plugins from the repository, not from my workspace" is to wrap our component 
and toggle the reader around the call. m2e disables 
EclipseWorkspaceArtifactRepository, NetBeans calls NbWorkspaceReader.silence(). 
IntelliJ's case is thinner — a retry decorator around our own implementation.

m2e's source still carries the citation:

Plugin realms are cached and there is currently no way to purge cached realms 
due to MNG-4194. Workspace plugins cannot be cached, so we disable this until 
MNG-4194 is fixed.
MNG-4194 is #5961 <https://github.com/apache/maven/issues/5961>, "API to safely 
release of plugin realms", opened in 2009 and closed in 2010 with the comment 
"Now working correctly in M2E". An API request, closed because the consumer's 
workaround worked. Sixteen years later the workaround is still there, in three 
products.

Maven 4 offers no alternative

org.apache.maven.api.spi 
<https://github.com/apache/maven/tree/maven-4.0.x/api/maven-api-spi/src/main/java/org/apache/maven/api/spi>
 currently contains ExtensibleEnumProvider, LanguageProvider, 
LifecycleProvider, ModelParser, ModelTransformer, PackagingProvider, 
PathScopeProvider, ProjectScopeProvider, PropertyContributor, TypeProvider and 
SpiService. All of it concerns the model, the lifecycle and the type system. 
Nothing touches artifact or plugin resolution.

So an embedder that needs to influence resolution has exactly one door, and it 
is the one we reserve the right to close without notice. We then did change it, 
mid-RC-vote, and IntelliJ broke for every user of a project that declares core 
extensions.

Possible directions

I am not attached to any of these; I would like to know which one the project 
considers right.

Document the contract instead of adding API: state that plugin and extension 
resolution bypasses the WorkspaceReader. If that is the intended behaviour 
anyway, two of the three overrides disappear.
Make the distinction expressible — a session or request scoped flag, or a 
separate workspace reader for plugin resolution.
A minimal supported SPI for plugin/extension resolution.
Decide explicitly that embedders are on their own. That is a legitimate answer 
— Maven 4 deliberately shrank its public surface, and a resolution SPI is a 
real maintenance commitment. But then I think we should say so plainly, rather 
than leave one internal door ajar and let three IDEs walk through it for 
fifteen years.
Whatever we choose, adding methods to a widely implemented interface as default 
rather than abstract costs us nothing and avoids this class of breakage — 
that part is just hygiene.

On timing: I am explicitly not proposing this as a 4.0.0 blocker — the fix in 
PR #13069 is what 4.0.0 needs. But I would not want to rule 4.0.0 out either. 
If the answer turns out to be option 1, or a very small additive SPI, it may be 
worth weighing whether it still fits before GA rather than waiting for 4.1 — 
an addition made after GA is harder to place than one made with it. That 
judgement is the project's, not mine.

Input from the IDE side would be worth more than my reading of their source. 
Marit van Dijk, Nikita Skvortsov, Sergey Chernov (JetBrains) what do you 
actually need from Maven here, and would option 1 or 2 be enough to let you 
drop the override? The same question to whoever is closest to m2e and NetBeans.

Regards,
Gerd

--
Gerd Aschemann (er/he) --- Veröffentlichen heißt Verändern (Carmen Thomas)
+49/173/3264070 -- [email protected] -- https://aschemann.net

Reply via email to