From 34a116d2f840707b8f2984c6a649a9d1144895f3 Mon Sep 17 00:00:00 2001 From: Divyansh Vijayvergia Date: Mon, 29 Jun 2026 12:06:56 +0000 Subject: [PATCH] Add JDK 17 fallback to mvn-spotless-apply.sh scripts/mvn-spotless-apply.sh previously exec'd `mvn spotless:apply` directly, so when the default JDK was older than 17 (the minimum required by the pinned google-java-format 1.27.0) it failed with no recovery. Mirror the `make fmt` -> `make fmt-jdk17` fallback: try the selected JDK first, and if that fails retry under an explicit JDK 17 install, always applying the javac --add-exports flags GJF needs on JDK 16+. To keep the fallback honest and portable: - detect the JDK version from the JVM Maven actually uses ($JAVA_HOME/bin/java if JAVA_HOME is set, else `java` on PATH), so the add-exports gating matches the running JDK and re-running with JAVA_HOME= succeeds on the first attempt; - allow the fallback location to be overridden via JDK17_HOME for non-Debian layouts, and error clearly (pointing at JDK17_HOME / JAVA_HOME) when no JDK 17 is found. --- NEXT_CHANGELOG.md | 3 ++ scripts/mvn-spotless-apply.sh | 62 +++++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 1b2ce9040..4fd053c6c 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -14,4 +14,7 @@ ### Internal Changes +- Added a JDK 17 fallback to `scripts/mvn-spotless-apply.sh` so `spotless:apply` still + formats when the default JDK is older than 17 (mirroring the `make fmt` behaviour). + ### API Changes diff --git a/scripts/mvn-spotless-apply.sh b/scripts/mvn-spotless-apply.sh index 822bc4736..14f6e245d 100755 --- a/scripts/mvn-spotless-apply.sh +++ b/scripts/mvn-spotless-apply.sh @@ -4,25 +4,67 @@ # google-java-format on JDK 16+. Without these, GJF fails on JDK 17+ with either # IllegalAccessError or NoSuchMethodError when it reaches into com.sun.tools.javac.*. # On JDK <= 15 the flags are unrecognized and would break Maven startup, so we only -# set them when detected JDK major version is >= 16. +# set them when the detected JDK major version is >= 16. +# +# If that JDK can't run google-java-format (most often because it's older than JDK 17, +# which the pinned GJF 1.27.0 requires), we retry under an explicit JDK 17 install — +# mirroring the `make fmt` -> `make fmt-jdk17` fallback. Override the fallback location +# with JDK17_HOME, or just point JAVA_HOME at a JDK 17+ and re-run. set -euo pipefail -JDK_VERSION_OUTPUT=$(java -version 2>&1 | head -1) -# Matches `"1.8.0_xxx"` (legacy) and `"17.0.1"` / `"25"` (modern) forms. -JDK_MAJOR=$(echo "$JDK_VERSION_OUTPUT" | sed -E 's/.*version "([0-9]+)(\.[0-9]+)?.*/\1/') -if [ "$JDK_MAJOR" = "1" ]; then - JDK_MAJOR=$(echo "$JDK_VERSION_OUTPUT" | sed -E 's/.*version "1\.([0-9]+).*/\1/') -fi +# Location used by the JDK 17 fallback. Override for non-Debian layouts, e.g. +# `JDK17_HOME=$(/usr/libexec/java_home -v 17) bash scripts/mvn-spotless-apply.sh`. +JDK17_HOME="${JDK17_HOME:-/usr/lib/jvm/java-17-openjdk-amd64}" -if [ "${JDK_MAJOR:-0}" -ge 16 ]; then - export MAVEN_OPTS="${MAVEN_OPTS:-} \ +# The --add-exports flags google-java-format needs to reach into com.sun.tools.javac.* +# on JDK 16+. +GJF_ADD_EXPORTS="\ --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" + +# Detect the major version of the JDK Maven will actually use: $JAVA_HOME/bin/java when +# JAVA_HOME is set, otherwise `java` from PATH. mvn resolves its JVM the same way, so the +# add-exports gating below matches what the first attempt really runs (and re-running with +# JAVA_HOME pointed at a JDK 17+ makes that attempt succeed without hitting the fallback). +JAVA_BIN="java" +if [ -n "${JAVA_HOME:-}" ] && [ -x "${JAVA_HOME}/bin/java" ]; then + JAVA_BIN="${JAVA_HOME}/bin/java" +fi + +JDK_VERSION_OUTPUT=$("$JAVA_BIN" -version 2>&1 | head -1) +# Matches `"1.8.0_xxx"` (legacy) and `"17.0.1"` / `"25"` (modern) forms. +JDK_MAJOR=$(echo "$JDK_VERSION_OUTPUT" | sed -E 's/.*version "([0-9]+)(\.[0-9]+)?.*/\1/') +if [ "$JDK_MAJOR" = "1" ]; then + JDK_MAJOR=$(echo "$JDK_VERSION_OUTPUT" | sed -E 's/.*version "1\.([0-9]+).*/\1/') +fi + +DEFAULT_OPTS="${MAVEN_OPTS:-}" +if [ "${JDK_MAJOR:-0}" -ge 16 ]; then + DEFAULT_OPTS="$DEFAULT_OPTS $GJF_ADD_EXPORTS" +fi + +# First attempt: the JDK selected above (JAVA_HOME or PATH). +if MAVEN_OPTS="$DEFAULT_OPTS" mvn spotless:apply; then + exit 0 +fi + +echo "" +echo "==> default JDK could not run google-java-format (likely < JDK 17). Retrying with JDK 17..." +echo "" + +if [ ! -x "$JDK17_HOME/bin/java" ]; then + echo "error: JDK 17 not found at $JDK17_HOME" >&2 + echo " install it, set JDK17_HOME to a JDK 17 install, or point JAVA_HOME" >&2 + echo " at a JDK 17+ and re-run." >&2 + exit 1 fi -exec mvn spotless:apply +# JDK 17 is always >= 16, so the add-exports flags are always required here. +exec env JAVA_HOME="$JDK17_HOME" \ + MAVEN_OPTS="${MAVEN_OPTS:-} $GJF_ADD_EXPORTS" \ + mvn spotless:apply