Skip to content

Introduce TempFileService and lifecycle cleanup participant - #11405

Open
arturobernalg wants to merge 1 commit into
apache:masterfrom
arturobernalg:11384-master
Open

arturobernalg wants to merge 1 commit into
apache:masterfrom
arturobernalg:11384-master

Conversation

@arturobernalg

Copy link
Copy Markdown
Member

Following this checklist to help us incorporate your
contribution quickly and easily:

[X ] Your pull request should address just one issue, without pulling in other changes.
[ X] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
[ X] Each commit in the pull request should have a meaningful subject line and body.
Note that commits might be squashed by a maintainer on merge.
[X ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied.
This may not always be possible but is a best-practice.
[X ] Run mvn verify to make sure basic checks pass.
A more thorough check will be performed on your pull request automatically.

You have run the [Core IT](https://maven.apache.org/core-its/core-it-suite/) successfully.

If your pull request is about ~20 lines of code you don't need to sign an
Individual Contributor License Agreement if you are unsure
please ask on the developers list.

To make clear that you license your contribution under
the Apache License Version 2.0, January 2004
you have to acknowledge this by using the following check-box.

I hereby declare this contribution to be licenced under the Apache License Version 2.0, January 2004
In any other case, please file an Apache Individual Contributor License Agreement.

@gnodet

gnodet commented Nov 7, 2025

Copy link
Copy Markdown
Contributor

It looks like a duplicate of #11389 ?

@arturobernalg

Copy link
Copy Markdown
Member Author

It looks like a duplicate of #11389 ?

Yes. one for master and the other for maven-4.X

@gnodet gnodet left a comment

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.

Small change needed

* System property to keep temp material for diagnostics.
*
*/
public static final String KEEP_PROP = "maven.tempfile.keep";

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.

Rename to MAVEN_TEMPFILE_KEEP for consistency.

@gnodet gnodet added this to the 4.1.0 milestone Nov 18, 2025
@gnodet gnodet added the enhancement New feature or request label Nov 18, 2025
@gnodet gnodet changed the title Introduce TempFileService and lifecycle cleanup participant for Maven 3. Introduce TempFileService and lifecycle cleanup participant Dec 3, 2025
@gnodet gnodet added the mvn4 label Jun 22, 2026

@gnodet gnodet left a comment

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.

Review: Introduce TempFileService and lifecycle cleanup participant

The concept is sound — providing a managed temp file service with automatic cleanup at session end is a useful addition. However, there are several API design issues that should be addressed before merging into the Maven 4 API.

High

@Nonnull on void return methods — TempFileService.register() and cleanup() have @Nonnull on their void return type. This is semantically meaningless — void methods have no return value to be null or non-null. Other services (e.g., ArtifactManager.setPath()) do not annotate void returns with @Nonnull. Remove @Nonnull from these two methods and instead annotate the parameters.

Medium

  1. KEEP_PROP naming convention (Constants.java) — Every other constant in Constants.java uses the MAVEN_ prefix (113 occurrences). The new constant should follow suit: MAVEN_TEMPFILE_KEEP instead of KEEP_PROP.

  2. Missing @Experimental annotation (TempFileService.java) — Every other Service interface in org.apache.maven.api.services carries @Experimental (ArtifactResolver, ArtifactManager, Interpolator, etc.). This should too.

  3. Boolean.getBoolean(KEEP_PROP) reads JVM system property (DefaultTempFileService.java) — Boolean.getBoolean() only checks System.getProperty(), so the property cannot be set via pom.xml <properties>, profiles, or settings.xml. Consider using session.getUserProperties() or session.getSystemProperties() if this should be settable through Maven's property resolution. If this is intentionally a JVM-level diagnostic flag, that's fine — just document the rationale.

  4. Missing @since and @Config (Constants.java) — All recent constant additions have @since 4.1.0 and a @Config annotation (e.g., MAVEN_CACHE_STATS, MAVEN_MODEL_PROCESSOR_POOLED_TYPES). Both are missing here.

Low

  1. Parameters missing @Nonnull/@Nullable (TempFileService.java) — Other services in this package annotate all parameters (Interpolator, ArtifactManager). The session and directory parameters should be @Nonnull; clarify whether prefix/suffix accept null (they do per java.nio.file.Files contract).

  2. Logger created inline (TempFileCleanupParticipant.java) — The logger is created at the call site: LoggerFactory.getLogger(TempFileCleanupParticipant.class).warn(...). This is inconsistent with DefaultTempFileService in the same PR, which correctly uses a private static final Logger LOGGER field. Extract to a field.

  3. System.setProperty in tests (DefaultTempFileServiceTest.java) — System.setProperty mutates global JVM state and can cause test pollution in parallel execution. Also, there is no test for TempFileCleanupParticipant itself.

  4. Raw type cast for TMP_KEY (DefaultTempFileService.java) — The @SuppressWarnings({"unchecked", "rawtypes"}) cast is acknowledged and documented. Consider a wrapper type to avoid the raw cast, or accept it as a known limitation of SessionData.Key generics.

Notes

  • The companion PR #11389 targeting maven-4.X is closed. Please confirm this is the intended target branch.
  • The PR description is minimal — for a new public API addition, documenting the motivation (what temp files are currently leaked, which plugins benefit) would help reviewers.
  • Thread safety looks correct: ConcurrentHashMap-backed Set and SessionData.computeIfAbsent provide atomic initialization.
  • No new dependencies introduced.

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

gnodet added a commit to gnodet/maven that referenced this pull request Jul 10, 2026
Reviewed 3 PRs: apache#12454 (re-review), apache#11502 (new), apache#11405 (new).
Added 2 new dependabot PRs to skip list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@gnodet gnodet left a comment

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.

New TempFileService API with lifecycle cleanup — solid concept for managing build temp files. All findings below were independently verified (7/7 confirmed).

Note: a maintainer (gnodet) already submitted CHANGES_REQUESTED in November 2025, and these issues remain unaddressed after 8+ months.

Convention violations:

  1. @nonnull on void returns (high) — register() and cleanup() apply @Nonnull to the void return type. Existing services apply it to parameters instead.
  2. Missing @experimental (medium) — All 20+ Service interfaces carry @Experimental. Also missing @since 4.1.0.
  3. KEEP_PROP naming (medium) — All 113 other constants use the MAVEN_ prefix. Should be MAVEN_TEMPFILE_KEEP. Also missing @Config and @since 4.1.0. (Already noted by gnodet in Nov 2025 review.)
  4. Boolean.getBoolean limitation (medium) — Only reads JVM -D properties, not Maven session properties from pom.xml/profiles/settings.xml. Should be documented if intentional.
  5. Inline logger (low) — TempFileCleanupParticipant creates logger inline; DefaultTempFileService uses standard private static final Logger.
  6. Missing parameter annotations (low) — session, directory, prefix, suffix parameters lack @Nonnull/@Nullable.
  7. System.setProperty in test (low) — Mutates global JVM state; @AfterEach cleanup present but can still cause flakiness under parallel execution. No test for TempFileCleanupParticipant.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of gnodet

* Registers an externally created path for cleanup at session end.
*/
@Nonnull
void register(Session session, Path path);

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.

@Nonnull on a void return type is semantically meaningless. In existing services (ArtifactDeployer.deploy, ArtifactManager.setPath), @Nonnull is applied to parameters, not void returns.

Same issue on cleanup() below.

Suggested change
void register(Session session, Path path);
void register(@Nonnull Session session, @Nonnull Path path);

* System property to keep temp material for diagnostics.
*
*/
public static final String KEEP_PROP = "maven.tempfile.keep";

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.

All 113 other constants in this file use the MAVEN_ prefix (MAVEN_HOME, MAVEN_CACHE_STATS, MAVEN_REPO_LOCAL, etc.). This should be MAVEN_TEMPFILE_KEEP. Also missing @since 4.1.0 and @Config annotation (71 other constants have @Config).

Suggested change
public static final String KEEP_PROP = "maven.tempfile.keep";
/**
* System property to keep temp material for diagnostics.
*
* @since 4.1.0
*/
@Config(type = "java.lang.Boolean", defaultValue = "false")
public static final String MAVEN_TEMPFILE_KEEP = "maven.tempfile.keep";

@gnodet gnodet left a comment

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.

Review Summary

The TempFileService design is clean and follows Maven 4 service conventions well — using SessionData for per-session tracking, @Singleton supporting multiple sessions, and the AbstractMavenLifecycleParticipant for cleanup are all consistent with existing patterns.

The existing review feedback from @gnodet (constant naming to MAVEN_TEMPFILE_KEEP, adding @Config/@since, removing @Nonnull on void methods) appears to have been addressed in the second commit.

Two robustness issues in the deleteTree cleanup logic and a minor test coverage gap:

1. 🐛 Missing visitFileFailed override in deleteTree (medium)

File: impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTempFileService.java

The SimpleFileVisitor in deleteTree does not override visitFileFailed. The default implementation re-throws the IOException, causing walkFileTree to abort immediately. On Windows where files can be locked by antivirus or other processes, a single inaccessible file prevents cleanup of the entire directory tree.

Suggestion: Override visitFileFailed to log and return CONTINUE for best-effort cleanup:

@Override
public FileVisitResult visitFileFailed(final Path file, final IOException exc) {
    LOGGER.debug("Could not access temp file for deletion: {}", file, exc);
    return FileVisitResult.CONTINUE;
}

2. 🐛 postVisitDirectory should catch DirectoryNotEmptyException (medium)

File: impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTempFileService.java

The postVisitDirectory override silently drops the exc parameter but does not wrap Files.deleteIfExists(dir) in a try-catch. If any children were not deleted (e.g., due to a locked file after fixing issue 1), deleteIfExists throws DirectoryNotEmptyException, which propagates through walkFileTree and aborts cleanup of the remaining tree.

Suggestion: Wrap in try-catch for best-effort cleanup:

@Override
public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) {
    try {
        Files.deleteIfExists(dir);
    } catch (final IOException e) {
        LOGGER.debug("Could not delete temp directory: {}", dir, e);
    }
    return FileVisitResult.CONTINUE;
}

These two issues are interrelated — fixing #1 makes #2 more likely to trigger, so both should be addressed together.

3. Missing test coverage (low)

File: impl/maven-core/src/test/java/org/apache/maven/internal/impl/DefaultTempFileServiceTest.java

The tests only exercise the no-directory overloads. The directory-parameter overloads (createTempFile(session, prefix, suffix, directory) and createTempDirectory(session, prefix, directory)) exercise different Files.createTempFile(directory, ...) / Files.createTempDirectory(directory, ...) code paths and have their own Objects.requireNonNull(directory) guard, none of which is tested.


🤖 This review was generated by ForgeBot. Feedback? File an issue on the ForgeBot repo.

@gnodet
gnodet force-pushed the 11384-master branch 2 times, most recently from f97429a to 4f46518 Compare September 2, 2026 12:15
@arturobernalg

Copy link
Copy Markdown
Member Author

Rebased on master and squashed. The earlier requests are already in (MAVEN_TEMPFILE_KEEP with @Config and @since, no @Nonnull on void methods, static logger, best-effort deleteTree, tests for the directory overloads and the cleanup participant). One remaining nit: a test still sets the keep property through System.setProperty.

@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.

All prior findings from @gnodet's review (November 2025) and subsequent bot reviews have been addressed in the squashed commit: MAVEN_TEMPFILE_KEEP naming ✓, @Config/@since ✓, @Nonnull removed from void returns ✓, @Experimental ✓, static logger in TempFileCleanupParticipant ✓, visitFileFailed override ✓, postVisitDirectory try-catch ✓, directory-overload tests ✓, and parameter null annotations ✓.

Two remaining issues prevent a clean merge.

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

Comment thread api/maven-api-core/src/main/java/org/apache/maven/api/Constants.java Outdated
Add TempFileService, an experimental API to create temporary files and
directories which are tracked per session, and delete them at the end of the
session through a lifecycle participant. Cleanup is best effort: a file which
cannot be deleted does not prevent the deletion of the others. Setting the
maven.tempfile.keep system property to true keeps them for diagnostics.

@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.

👋 Re-reviewing after the new squash commit.

✅ All four prior findings are addressed:

  • @Config source corrected and @throws added throughout
  • Stack trace preserved in exception handling
  • @throws added to all factory methods and cleanup()
  • System.setProperty now guarded with try-finally

One new issue remains.

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

* @throws IOException if the path cannot be created
*/
@Nonnull
Path createTempFile(@Nonnull Session session, @Nullable String prefix, @Nullable String suffix) throws IOException;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📝 Missing @param and @return tags on all factory methods

All six methods in this interface have Javadoc but are missing @param and @return documentation. Every other Maven 4 API service interface (ArtifactResolver, DependencyResolver, VersionResolver, etc.) consistently documents all parameters and return values with Javadoc tags.

For example, createTempFile(Session, String, String) should read:

Suggested change
Path createTempFile(@Nonnull Session session, @Nullable String prefix, @Nullable String suffix) throws IOException;
/**
* Creates a temp file in the default temp directory.
*
* @param session the Maven session, must not be {@code null}
* @param prefix the prefix string to be used in generating the file's name; may be {@code null}
* @param suffix the suffix string to be used in generating the file's name; may be {@code null}
* @return the path to the newly created temp file, never {@code null}
* @throws IOException if the path cannot be created
*/

Please add @param and @return tags to all six methods (createTempFile ×2, createTempDirectory ×2, register, cleanup).

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.

3 participants