From 3442afd4eb0442ec81eb8600ee4ced769027dcd1 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Thu, 3 Apr 2025 13:49:24 +0200 Subject: [PATCH] GH-1133 - More resilient APT output location detection. Gradle's APT handling seems to significantly differ from Maven's as the Java compilation runs from a completely different base folder than the actual project compiled. Even more so, for multi-module projects, the base folder is always the same, which causes APT output using Java's plain File API to override itself in a multi-module project. I've tweaked the output folder detection to look up well-known APT parameters provided by either the Spring Boot plugin (org.springframework.boot.configurationprocessor.additionalMetadataLocations) or KAPT (for Kotlin-based projects, kapt.kotlin.generated) and derive the actual output folder from the values set for those. If neither of these is set, we fall back to the original local folder. --- .../modulith/apt/SpringModulithProcessor.java | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/spring-modulith-apt/src/main/java/org/springframework/modulith/apt/SpringModulithProcessor.java b/spring-modulith-apt/src/main/java/org/springframework/modulith/apt/SpringModulithProcessor.java index 9a82e1f5..04008243 100644 --- a/spring-modulith-apt/src/main/java/org/springframework/modulith/apt/SpringModulithProcessor.java +++ b/spring-modulith-apt/src/main/java/org/springframework/modulith/apt/SpringModulithProcessor.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -70,6 +71,7 @@ public class SpringModulithProcessor implements Processor { private Elements elements; private Messager messager; + private File javadocJson; private boolean testExecution; private Set metadata = new HashSet<>(); @@ -123,6 +125,7 @@ public class SpringModulithProcessor implements Processor { this.elements = environment.getElementUtils(); this.messager = environment.getMessager(); + this.javadocJson = getAptOutputFolder(environment).resolve(JSON_LOCATION).toFile(); try { @@ -165,8 +168,6 @@ public class SpringModulithProcessor implements Processor { if (roundEnv.processingOver()) { - messager.printMessage(Kind.NOTE, "Extracting Javadoc into " + JSON_LOCATION + "."); - var methodJson = JsonWriter. of(inner -> { inner.add("name", MethodMetadata::name); inner.add("signature", MethodMetadata::signature); @@ -185,11 +186,11 @@ public class SpringModulithProcessor implements Processor { }); }); - File file = new File(JSON_LOCATION); + messager.printMessage(Kind.NOTE, "Extracting Javadoc into " + javadocJson.getAbsolutePath() + "."); - if (!file.exists()) { + if (!javadocJson.exists()) { try { - Files.createDirectories(file.toPath().getParent()); + Files.createDirectories(javadocJson.toPath().getParent()); } catch (IOException e) { throw new RuntimeException(e); } @@ -202,7 +203,7 @@ public class SpringModulithProcessor implements Processor { .map(typeJson::write) .toList()); - try (var writer = new FileWriter(file)) { + try (var writer = new FileWriter(javadocJson)) { writer.write(output); } catch (IOException e) { throw new RuntimeException(e); @@ -305,4 +306,22 @@ public class SpringModulithProcessor implements Processor { return Stream.concat(Stream.of(type), enclosed); } + + private static Path getAptOutputFolder(ProcessingEnvironment environment) { + + var boot = environment.getOptions() + .get("org.springframework.boot.configurationprocessor.additionalMetadataLocations"); + + if (boot != null) { + return Path.of(boot.substring(0, boot.indexOf("/src/main/resources"))); + } + + var kapt = environment.getOptions().get("kapt.kotlin.generated"); + + if (kapt != null) { + return Path.of(kapt.substring(0, kapt.indexOf("/build/generated/source"))); + } + + return Path.of("."); + } }