Skip to content

Avoid a checked IOException in field initializers in TemporaryFolderToTempDir - #1280

Merged
timtebeek merged 3 commits into
mainfrom
temporaryfolder-field-initializer
Nov 3, 2026
Merged

timtebeek merged 3 commits into
mainfrom
temporaryfolder-field-initializer

Conversation

@timtebeek

Copy link
Copy Markdown
Member

TemporaryFolderToTempDir turns a TemporaryFolder field without @Rule or @ClassRule into a File initialized with Files.createTempDirectory("junit").toFile(). That method throws the checked IOException, which a field initializer cannot throw, so the class no longer compiles.

Before:

TemporaryFolder serverGitFolder = new TemporaryFolder();

After (does not compile: unreported exception IOException):

File serverGitFolder = Files.createTempDirectory("junit").toFile();

This surfaced while validating the Spring Boot 4.1 migration over open source Spring Boot 3.x repositories, in xm-online/xm-ms-config: LocalJGitRepositoryConfiguration, a Spring @Configuration in the test sources, holds three plain TemporaryFolder fields and calls create() on them itself.

Skipping such fields, or the file, would move the problem: the file also declares public static helpers that take a TemporaryFolder, and JGitRepositoryIntTest passes its @Rule TemporaryFolder fields to them. That test is converted to @TempDir File either way, so the helpers' parameters have to become File too.

This change keeps the conversion, and for a field initializer in Java it calls a private static helper that the recipe adds to the class:

File serverGitFolder = createTempDirectory();

private static File createTempDirectory() {
    try {
        return Files.createTempDirectory("junit").toFile();
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
}

When the class already has a no-argument method of that name, the helper is called createTempDirectory2 (and so on). Local variables, arguments and Groovy are unchanged.

Is this the right change?

  • Do we already have it? No. Handle non-@Rule TemporaryFolder fields #720 added the conversion of fields without a rule, but not for the checked exception.
  • Could it be declarative? No, it depends on where the constructor call sits.
  • Is it worth it? Yes, a plain TemporaryFolder field is a common way to get a temporary directory outside a rule, and the result does not compile.
  • Does it fix the problem, or move it? It fixes it; the field and every method that receives it stay File, as before.
  • Does it do no harm? @Rule/@ClassRule fields still become @TempDir without an initializer. The directory is created when the field is initialized rather than at create(), which the recipe already removed.

Tests: TemporaryFolderToTempDirTest: new fieldNotAsRule (instance and static fields, create() and getRoot() in methods and on a parameter; failed before) and ruleFieldNextToPlainFieldAndExistingHelperName (a @Rule field next to a plain one, with an existing createTempDirectory()). TemporaryFolderToTempDirTest, JUnit5MigrationTest, UseWiremockExtensionTest, HandleExternalResourceRulesTest, RemoveJupiterMigrationSupportTest, TimeoutRuleToClassAnnotationTest and MockitoJUnitToMockitoExtensionTest pass.

@timtebeek
timtebeek enabled auto-merge (squash) November 3, 2026 13:05
@timtebeek
timtebeek merged commit c7bcb6d into main Nov 3, 2026
1 check passed
@timtebeek
timtebeek deleted the temporaryfolder-field-initializer branch November 3, 2026 13:07
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant