Conversation
Move the main class defaulting from classworlds property resolution to
Java code. MavenCling is now hardcoded as the entry point in m2.conf
and delegates to the class specified by -Dmaven.mainClass via
reflection when set. This fixes the Maven Wrapper and IDE integration
by removing the dependency on classworlds resolving ${maven.mainClass}.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet
left a comment
There was a problem hiding this comment.
Clean, well-motivated fix that moves the maven.mainClass dispatch from classworlds property resolution to Java-level reflection in MavenCling. The approach eliminates the root cause of Maven Wrapper and IDE failures and follows the design suggested in the original issue discussion.
All four known delegation targets (MavenCling, MavenEncCling, MavenShellCling, MavenUpCling) have the expected public static int main(String[], ClassWorld) signature, and the error handling in delegateMain is thorough.
The PR description and behavior matrix are excellent. The approach of hardcoding MavenCling in m2.conf and delegating in Java is strictly more robust than the previous classworlds-level default (PR #10998), since it eliminates classworlds property resolution from the critical path entirely.
Minor observations:
- The
instanceofchecks indelegateMainuse old-style casts rather than pattern matching instanceof, which is used elsewhere in the codebase (Java 17 target). Minor style inconsistency. - Tests cover delegation scenarios well but miss the two no-delegation paths: (1) when
maven.mainClassis not set (null), and (2) when it is set toMavenClingitself. While these paths are simple, explicit tests would document the contract. - Tests mutate the global
maven.mainClasssystem property — the try/finally cleanup is correct, but this could cause flaky failures if tests run in parallel within the same JVM.
📋 PR Metadata
| Aspect | Current | Suggested |
|---|---|---|
| Labels | (none) | bug |
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
| set maven.mainClass default org.apache.maven.cling.MavenCling | ||
|
|
||
| main is ${maven.mainClass} from plexus.core | ||
| main is org.apache.maven.cling.MavenCling from plexus.core |
There was a problem hiding this comment.
I don't know the syntax here but is this right? Is this supposed to be a comment?
Now that MavenCling is the hardcoded entry point (#12875) and delegates via maven.mainClass, the IT can use "mvn --up" instead of the separate "mvnup" script. This eliminates the chmod workaround for CI environments where zip extraction loses Unix execute permissions. Also use orElseGet for optional element creation (review feedback). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…fig (#12875) (#12889) Move the main class defaulting from classworlds property resolution to Java code. MavenCling is now hardcoded as the entry point in m2.conf and delegates to the class specified by -Dmaven.mainClass via reflection when set. This fixes the Maven Wrapper and IDE integration by removing the dependency on classworlds resolving ${maven.mainClass}. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Now that MavenCling is the hardcoded entry point (#12875) and delegates via maven.mainClass, the IT can use "mvn --up" instead of the separate "mvnup" script. This eliminates the chmod workaround for CI environments where zip extraction loses Unix execute permissions. Also use orElseGet for optional element creation (review feedback). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Fixes #2520 — Maven Wrapper (and IDEs like IntelliJ) broken with Maven 4.0.0-beta-5+ because
maven.mainClassis not set when launching through external tools.Root cause:
m2.confusedmain is ${maven.mainClass}which required classworlds property resolution. When external tools bypassed themvnscripts,-Dmaven.mainClasswas never set, causingConfigurationException: No such property: maven.mainClass. The previous fix (PR #10998, rc-5) addedset maven.mainClass defaultinm2.conf, but this kept the defaulting in classworlds config rather than Java — as noted by @gnodet in the issue discussion.Fix: Move the main class defaulting from classworlds property resolution to Java code:
m2.conf: Hardcodemain is org.apache.maven.cling.MavenCling from plexus.core— no variable resolution needed, no possibility of classworldsConfigurationExceptionMavenCling.java: Checkmaven.mainClasssystem property in the ClassWorld Launcher entry point and delegate to the specified class via reflection when set (e.g.,MavenEncCling,MavenShellCling,MavenUpCling)This makes
MavenClingthe Java-level default entry point that all external tools can rely on without any special configuration.Behavior
mvnscript (normal)-Dmaven.mainClass=MavenCling→ classworlds resolves-Dmaven.mainClass=MavenCling→ classworlds callsMavenCling→ no dispatchmvn --enc-Dmaven.mainClass=MavenEncCling→ classworlds resolves-Dmaven.mainClass=MavenEncCling→MavenClingdelegates toMavenEncCling-Dmaven.mainClass)m2.confdefault resolvesMavenClingdirectly — no resolution needed-Dmaven.mainClass)m2.confdefault resolvesMavenClingdirectly — no resolution neededTest plan
MavenClingTestwith 3 tests: delegation to valid class, unknown class error, missing method errormvn verify -pl impl/maven-cli -DskipTests— build + format checks pass🤖 Generated with Claude Code