From 048b6bdd88ae16213e46f02702ebe93811a9b8aa Mon Sep 17 00:00:00 2001 From: Robert Winch <362503+rwinch@users.noreply.github.com> Date: Fri, 16 Jan 2026 10:51:42 -0600 Subject: [PATCH] Update to JDK 25 (release = 17) This commit updates the build to use JDK 25 while remaining compatable with JDK 17. Note that we must update our JAAS related tests to use release=25 due to the disabling of the Security Manager. See https://docs.oracle.com/en/java/javase/25/security/security-manager-is-permanently-disabled.html Closes gh-18512 --- .github/workflows/check-snapshots.yml | 6 ++-- .../continuous-integration-workflow.yml | 2 +- .../gradle-wrapper-upgrade-execution.yml | 4 +-- .github/workflows/pr-build-workflow.yml | 4 +-- .sdkmanrc | 2 +- build.gradle | 12 ++++++-- .../groovy/test-compile-target-jdk25.gradle | 30 +++++++++++++++++++ config/spring-security-config.gradle | 1 + .../config/http/MiscHttpConfigTests.java | 3 +- web/spring-security-web.gradle | 1 + .../JaasApiIntegrationFilterTests.java | 5 ++-- 11 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 buildSrc/src/main/groovy/test-compile-target-jdk25.gradle diff --git a/.github/workflows/check-snapshots.yml b/.github/workflows/check-snapshots.yml index f482c0459f..f14526a76b 100644 --- a/.github/workflows/check-snapshots.yml +++ b/.github/workflows/check-snapshots.yml @@ -18,10 +18,8 @@ jobs: strategy: matrix: include: - - java-version: 21-ea - toolchain: 21 - - java-version: 17 - toolchain: 17 + - java-version: 25 + toolchain: 25 with: java-version: ${{ matrix.java-version }} test-args: --refresh-dependencies -PforceMavenRepositories=snapshot,https://oss.sonatype.org/content/repositories/snapshots -PisOverrideVersionCatalog -PtestToolchain=${{ matrix.toolchain }} -PspringFrameworkVersion=7.+ -PreactorVersion=2025.+ -PspringDataVersion=2025.+ --stacktrace diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index 12e9eec754..cb07005577 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -21,7 +21,7 @@ jobs: strategy: matrix: os: [ ubuntu-latest, windows-latest ] - jdk: [ 17 ] + jdk: [ 25 ] with: runs-on: ${{ matrix.os }} java-version: ${{ matrix.jdk }} diff --git a/.github/workflows/gradle-wrapper-upgrade-execution.yml b/.github/workflows/gradle-wrapper-upgrade-execution.yml index 8207edddef..7886f32425 100644 --- a/.github/workflows/gradle-wrapper-upgrade-execution.yml +++ b/.github/workflows/gradle-wrapper-upgrade-execution.yml @@ -20,10 +20,10 @@ jobs: git config --global user.email 'github-actions[bot]@users.noreply.github.com' - name: Checkout uses: actions/checkout@v4 - - name: Set up JDK 17 + - name: Set up JDK 25 uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '25' distribution: 'temurin' - name: Set up Gradle uses: gradle/gradle-build-action@v2 diff --git a/.github/workflows/pr-build-workflow.yml b/.github/workflows/pr-build-workflow.yml index 2ebf86c76b..5578899d8b 100644 --- a/.github/workflows/pr-build-workflow.yml +++ b/.github/workflows/pr-build-workflow.yml @@ -15,7 +15,7 @@ jobs: - name: Set up gradle uses: spring-io/spring-gradle-build-action@v2 with: - java-version: '17' + java-version: '25' distribution: 'temurin' - name: Build with Gradle run: ./gradlew clean build -PskipCheckExpectedBranchVersion --continue --scan @@ -28,7 +28,7 @@ jobs: - name: Set up gradle uses: spring-io/spring-gradle-build-action@v2 with: - java-version: '17' + java-version: '25' distribution: 'temurin' - name: Run Antora run: ./gradlew -PbuildSrc.skipTests=true :spring-security-docs:antora diff --git a/.sdkmanrc b/.sdkmanrc index 64345a4be3..f6c602d589 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -3,4 +3,4 @@ # See https://sdkman.io/usage#config # A summary is to add the following to ~/.sdkman/etc/config # sdkman_auto_env=true -java=17.0.3-tem +java=25-librca diff --git a/build.gradle b/build.gradle index 33a1ae068e..acf92f6d59 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,7 @@ import io.spring.gradle.IncludeRepoTask +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import trang.RncToXsd +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile buildscript { dependencies { @@ -50,7 +52,7 @@ def toolchainVersion() { if (project.hasProperty('testToolchain')) { return project.property('testToolchain').toString().toInteger() } - return 17 + return 25 } subprojects { @@ -61,7 +63,7 @@ subprojects { } kotlin { jvmToolchain { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(toolchainVersion()) } } tasks.withType(JavaCompile).configureEach { @@ -69,6 +71,12 @@ subprojects { options.compilerArgs.add("-parameters") options.release.set(17) } + tasks.withType(KotlinCompile).configureEach { + compilerOptions { + javaParameters = true + jvmTarget.set(JvmTarget.JVM_17) + } + } } allprojects { diff --git a/buildSrc/src/main/groovy/test-compile-target-jdk25.gradle b/buildSrc/src/main/groovy/test-compile-target-jdk25.gradle new file mode 100644 index 0000000000..2a65969ece --- /dev/null +++ b/buildSrc/src/main/groovy/test-compile-target-jdk25.gradle @@ -0,0 +1,30 @@ +import org.gradle.api.tasks.compile.JavaCompile +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +/** + * We need to compile with JDK 25 for nullability support, but using JDK 25 means that our tests will fail due to the + * removal + * of the Java Security Manager. For example, in JDK 25 {@code Subject.getSubject(AccessControlContext)} throws an + * {@code UnsupportedOperationException}. + * + * To resolve this, we must migrate tests to use the new APIs (e.g. {@code Subject.current()}) but those APIs are not + * available in the JDK 17 source, so compiling with JDK 25 and release 17 fails. The plugin overrides the test + * compilation to use release 25. + * + * @see The + * Security Manager Is Permanently Disabled + * @see Quality Outreach Heads-up - JDK 23: Re-Specified + * Subject.getSubject API + */ + +tasks.withType(JavaCompile).configureEach { task -> + if (task.name == 'compileTestJava' || task.name == 'compileIntegrationTestJava') { + task.options.release.set(25) + } +} + +tasks.withType(KotlinCompile).configureEach { task -> + if (task.name == 'compileTestKotlin' || task.name == 'compileIntegrationTestKotlin') { + task.kotlinOptions.jvmTarget = '25' + } +} diff --git a/config/spring-security-config.gradle b/config/spring-security-config.gradle index d732cf4c2d..d5ba327bfe 100644 --- a/config/spring-security-config.gradle +++ b/config/spring-security-config.gradle @@ -4,6 +4,7 @@ import trang.RncToXsd apply plugin: 'io.spring.convention.spring-module' apply plugin: 'trang' apply plugin: 'security-kotlin' +apply plugin: 'test-compile-target-jdk25' configurations { opensaml5 { diff --git a/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java b/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java index 8a4a15821a..8406ba1527 100644 --- a/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java @@ -19,7 +19,6 @@ package org.springframework.security.config.http; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.security.AccessController; import java.security.Principal; import java.security.cert.X509Certificate; import java.util.Arrays; @@ -989,7 +988,7 @@ public class MiscHttpConfigTests { @GetMapping("/username") String username() { - Subject subject = Subject.getSubject(AccessController.getContext()); + Subject subject = Subject.current(); return subject.getPrincipals().iterator().next().getName(); } diff --git a/web/spring-security-web.gradle b/web/spring-security-web.gradle index 887966e47f..2be598a34d 100644 --- a/web/spring-security-web.gradle +++ b/web/spring-security-web.gradle @@ -1,6 +1,7 @@ plugins { id 'security-nullability' id 'javadoc-warnings-error' + id 'test-compile-target-jdk25' } apply plugin: 'io.spring.convention.spring-module' diff --git a/web/src/test/java/org/springframework/security/web/jaasapi/JaasApiIntegrationFilterTests.java b/web/src/test/java/org/springframework/security/web/jaasapi/JaasApiIntegrationFilterTests.java index c6b1cefbe3..eb510fa600 100644 --- a/web/src/test/java/org/springframework/security/web/jaasapi/JaasApiIntegrationFilterTests.java +++ b/web/src/test/java/org/springframework/security/web/jaasapi/JaasApiIntegrationFilterTests.java @@ -17,7 +17,6 @@ package org.springframework.security.web.jaasapi; import java.io.IOException; -import java.security.AccessController; import java.util.HashMap; import javax.security.auth.Subject; @@ -131,7 +130,7 @@ public class JaasApiIntegrationFilterTests { */ @Test public void currentSubjectNull() { - assertThat(Subject.getSubject(AccessController.getContext())).isNull(); + assertThat(Subject.current()).isNull(); } @Test @@ -207,7 +206,7 @@ public class JaasApiIntegrationFilterTests { public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // See if the subject was updated - Subject currentSubject = Subject.getSubject(AccessController.getContext()); + Subject currentSubject = Subject.current(); assertThat(currentSubject).isEqualTo(expectedValue); // run so we know the chain was executed super.doFilter(request, response);