Modernize codebase with Java improvements#2277
Conversation
|
Regarding point 2. (and the related point 4.): I consider the IAE more concise than an NPE in case a method argument is passed with null (although not allowed). Compare also with https://discuss.kotlinlang.org/t/why-does-requirenotnull-throw-an-illegalargumentexception/7617/4 |
|
I think that the main argument in favour of |
c52c814 to
b071032
Compare
Hi folks, please check out attached This could be supplemented in dedicated PR as there is a migration for this: Maybe we can team up with as its kind of related. The migration is "free" as done by one click so we can reproduce anytime. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I don't see where it's done in your PR as it only provides the result of executing the transformation. |
| @Override | ||
| public Session withLocalRepository(@Nonnull LocalRepository localRepository) { | ||
| nonNull(localRepository, "localRepository"); | ||
| Objects.requireNonNull(localRepository, "localRepository cannot be null"); |
There was a problem hiding this comment.
Current State of NullPointerException Handling
The current implementation around NullPointerException is not ideal, but in context, it's clear what's happening.
Options:
- Keep it as-is
- Works but lacks elegance.
- Remove all such checks
- Simplifies but loses explicit null-check messaging.
- Refactor into a dedicated layer
- Separate the "cannot be null" concern to avoid:
- DRY violations (repetition)
- Feature envy (fluff and copy-paste)
- Separate the "cannot be null" concern to avoid:
Proposal: Dedicated Logging Layer
If improved logging is desired, this concern should be moved to a dedicated utility layer, similar to Apache Maven's approach:
Benefits:
- Contextual clarity: Right now, the check is just a short "non-null" hint.
- Better debugging: Explicit messaging improves
NullPointerExceptionreadability. - Consistency: Centralized handling avoids duplication.
This change is already reflected in PR #2290.
| List<RemoteRepository> repositories, | ||
| List<org.eclipse.aether.repository.RemoteRepository> resolverRepositories, | ||
| Lookup lookup) { | ||
| this.session = nonNull(session, "session"); |
There was a problem hiding this comment.
Current State of NullPointerException Handling
The current implementation around NullPointerException is not ideal, but in context, it's clear what's happening.
Options:
- Keep it as-is
- Works but lacks elegance.
- Remove all such checks
- Simplifies but loses explicit null-check messaging.
- Refactor into a dedicated layer
- Separate the "cannot be null" concern to avoid:
- DRY violations (repetition)
- Feature envy (fluff and copy-paste)
- Separate the "cannot be null" concern to avoid:
Proposal: Dedicated Logging Layer
If improved logging is desired, this concern should be moved to a dedicated utility layer, similar to Apache Maven's approach:
Benefits:
- Contextual clarity: Right now, the check is just a short "non-null" hint.
- Better debugging: Explicit messaging improves
NullPointerExceptionreadability. - Consistency: Centralized handling avoids duplication.
This change is already reflected in PR #2290.
|
@Pankraz76 I'm not sure what you aim for with your PRs. How do they differ from this one ? It's fine very fine that you used openrewrite rules, but isn't the result the same at the end ? |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
"Use modern Java collections API (toList() instead of collect(Collectors.toList()))" is riskier than the other changes because of the move of mutable to immutable lists. Nine times out of ten this is fine. The tenth time it's a bear to debug. These changes should be pulled out into a separate PR.
The rest could be split, but maybe don't have to be. Nuulable and Nonnull might also call for a separate PR.
This comment has been minimized.
This comment has been minimized.
Java and Lombok prefer NPE as well. https://docs.oracle.com/javase/8/docs/api/java/util/Objects.html#requireNonNull-T- https://projectlombok.org/features/NonNull both valid points. Ideally its just one config-switch to adjust:
|
|
There 's no plan to use Lombok at this point. |
This comment has been minimized.
This comment has been minimized.
|
|
||
| @Override | ||
| public void registerListener(@Nonnull Listener listener) { | ||
| listeners.add(nonNull(listener)); |
There was a problem hiding this comment.
this is dedicated in:
if possible lets merge this first as this is kind of huge.
This comment has been minimized.
This comment has been minimized.
Reviewed 3 PRs: apache#982 (PowerShell 3.9.x, syntax bugs), apache#878 (PowerShell master, needs Maven 4 rewrite), apache#33 (qualityManagement, oldest PR at 11 years). 45 reviews posted total. Only 3 truly unreviewed PRs remain: apache#2277, apache#1774, apache#71 (all large). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet
left a comment
There was a problem hiding this comment.
AI Review — PR #2277: Modernize codebase with Java improvements
This is a large (191 files) but predominantly mechanical modernization PR by the project maintainer. Five categories of changes: @Nonnull/@Nullable annotations, Objects.requireNonNull replacing custom nonNull(), Stream.toList() replacing collect(Collectors.toList()), List.of()/Map.of() replacing Collections.emptyList()/singletonList(), and inner classes → records in Lifecycles.java.
toList() Mutability Concern
As elharo noted in their CHANGES_REQUESTED review, the toList() migration is the highest-risk category. Collectors.toList() returns a mutable ArrayList; Stream.toList() returns an unmodifiable list. Two specific call sites worth auditing:
1. ImplUtils.map() — Changes from collect(Collectors.toList()) to toList(). Callers that mutate the returned list will get UnsupportedOperationException. Sampled callers appear read-only, but a systematic audit would be prudent.
2. LifecycleDependencyResolver.getProjects() — Same pattern. Callers in MojoExecutor iterate without mutation, but the contract change is latent.
elharo's suggestion to split the toList() changes into a separate PR has merit — it isolates the mutability risk from the purely safe annotation/null-check changes.
What Looks Good
- The
Objects.requireNonNullmigration (from customImplUtils.nonNull()) is clean and complete — all call sites updated, dead methods removed - The
@Nonnull/@Nullableannotations improve IDE/static-analysis support - The
List.of()/Map.of()changes are safe — they replace already-immutableCollections.singletonList()/emptyList() - The null check improvement in
DefaultLifecycleBindingsInjector(adding guard beforeMap.ofwhich doesn't accept null) is a correctness fix
File paths are current — all sampled paths exist on master.
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
Reviewed final 3 PRs: apache#2277 (modernize codebase), apache#1774 (cascading profiles, found ReportSet merge bug), apache#71 (mirrors in profiles). 48 reviews posted total. All 61 open PRs have now been reviewed or skipped. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet
left a comment
There was a problem hiding this comment.
Code Review
The PR bundles five distinct refactoring categories across 191 files (annotation additions, exception type changes, Collections modernization, class-to-record conversions, null-check standardization). Two confirmed regressions were found in DefaultLifecycleRegistry:
-
WrappedPhase.plugins() returns ALL lifecycle plugins (
DefaultLifecycleRegistry.java:228): The newWrappedPhaserecord passes the entirelfPhasesmap toparseLifecyclePhaseDefinitions(lfPhases), which iterates ALL entries. The original code looked up only the current phase's plugins vialfPhases.get(name). Every phase would now incorrectly return plugins from every other phase. -
WrappedLifecycle.phases() drops extra default-phases support (
DefaultLifecycleRegistry.java:240): The PR branch (from May 2025, 653 commits behind master) predates fix #11796 (June 2026). TheWrappedLifecyclerecord only iterateslifecycle.getPhases(), omitting thebuildOwnPhases()helper and expanded phases logic that preserves plugin bindings fromcomponents.xmldefault-phasesentries. Merging this would revert fix #11796. -
Stream.toList() mutability (low, multiple files):
Stream.toList()produces unmodifiable lists whereascollect(Collectors.toList())returned mutableArrayLists. Already flagged by elharo's CHANGES_REQUESTED review recommending this be split into a separate PR.
Note: Three other reviewer findings were independently determined to be false positives (parseLifecyclePhaseDefinitions caller breakage, Phase.allPhases() default method compatibility, and CoreUtils exception type changes).
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet

This PR includes several improvements to modernize the codebase:
These changes make the code more maintainable, safer, and aligned with modern Java practices.