From 040e249592be38774fec0eff1dfdac6d6c305abc Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Tue, 2 Dec 2025 17:06:28 -0800 Subject: [PATCH 1/3] Support Java 25 --- .../org/labkey/api/module/JavaVersion.java | 26 ++++++++--- .../bootstrap/CoreWarningProvider.java | 44 +++++++++---------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/api/src/org/labkey/api/module/JavaVersion.java b/api/src/org/labkey/api/module/JavaVersion.java index 68ae5b0aedb..cf49b4d4608 100644 --- a/api/src/org/labkey/api/module/JavaVersion.java +++ b/api/src/org/labkey/api/module/JavaVersion.java @@ -31,8 +31,9 @@ public enum JavaVersion { JAVA_UNSUPPORTED(-1, true, false, null), - JAVA_17(17, false, true, "https://docs.oracle.com/en/java/javase/17/docs/api/java.base/"), - JAVA_FUTURE(Integer.MAX_VALUE, false, false, "https://docs.oracle.com/en/java/javase/17/docs/api/java.base/"); + JAVA_17(17, true, true, "https://docs.oracle.com/en/java/javase/17/docs/api/java.base/"), + JAVA_25(25, false, true, "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/"), + JAVA_FUTURE(Integer.MAX_VALUE, false, false, "https://docs.oracle.com/en/java/javase/25/docs/api/java.base/"); private final int _version; private final boolean _deprecated; @@ -73,7 +74,7 @@ public String getJavaDocBaseURL() public static JavaVersion get() { - // Determine current Java specification version, normalized to an int (e.g., 17, 18, 19, 20...). + // Determine current Java specification version, normalized to an int (e.g., 17, 20, 25, 31...). // Commons lang methods like SystemUtils.isJavaVersionAtLeast() aren't an option because that library isn't // released often enough to keep up with the Java rapid release cadence. String[] versionArray = SystemUtils.JAVA_SPECIFICATION_VERSION.split("\\."); @@ -109,7 +110,7 @@ public static String getJavaVersionDescription() public static String getRecommendedJavaVersion() { - return "Eclipse Temurin 17 64-bit with HotSpot JVM"; + return "Eclipse Temurin 25 64-bit with HotSpot JVM"; } public static class TestCase extends Assert @@ -131,12 +132,25 @@ public void test() test(15, JAVA_UNSUPPORTED); test(16, JAVA_UNSUPPORTED); + test(18, JAVA_UNSUPPORTED); + test(19, JAVA_UNSUPPORTED); + test(20, JAVA_UNSUPPORTED); + test(21, JAVA_UNSUPPORTED); + test(22, JAVA_UNSUPPORTED); + test(23, JAVA_UNSUPPORTED); + test(24, JAVA_UNSUPPORTED); + // Good test(17, JAVA_17); + test(25, JAVA_25); // Future - test(18, JAVA_FUTURE); - test(19, JAVA_FUTURE); + test(26, JAVA_FUTURE); + test(27, JAVA_FUTURE); + test(28, JAVA_FUTURE); + test(29, JAVA_FUTURE); + test(30, JAVA_FUTURE); + test(31, JAVA_FUTURE); } private void test(int version, JavaVersion expectedVersion) diff --git a/core/src/org/labkey/core/view/template/bootstrap/CoreWarningProvider.java b/core/src/org/labkey/core/view/template/bootstrap/CoreWarningProvider.java index ce0c405fe77..65313a32277 100644 --- a/core/src/org/labkey/core/view/template/bootstrap/CoreWarningProvider.java +++ b/core/src/org/labkey/core/view/template/bootstrap/CoreWarningProvider.java @@ -111,13 +111,13 @@ public void addStaticWarnings(@NotNull Warnings warnings, boolean showAllWarning DbScope labkeyScope = DbScope.getLabKeyScope(); labkeyScope.getSqlDialect().addAdminWarningMessages(warnings, showAllWarnings); - getHeapSizeWarnings(warnings, showAllWarnings); + addHeapSizeWarnings(warnings, showAllWarnings); - getConnectionPoolSizeWarnings(warnings, labkeyScope, showAllWarnings); + addConnectionPoolSizeWarnings(warnings, labkeyScope, showAllWarnings); - getJavaWarnings(warnings, showAllWarnings); + addJavaWarnings(warnings, showAllWarnings); - getTomcatWarnings(warnings, showAllWarnings); + addTomcatWarnings(warnings, showAllWarnings); } @Override @@ -131,19 +131,19 @@ public void addDynamicWarnings(@NotNull Warnings warnings, @Nullable ViewContext if (context == null || context.getUser().hasRootPermission(TroubleshooterPermission.class)) { - getUserRequestedAdminOnlyModeWarnings(warnings, showAllWarnings, context == null || context.getUser().hasSiteAdminPermission()); + addUserRequestedAdminOnlyModeWarnings(warnings, showAllWarnings, context == null || context.getUser().hasSiteAdminPermission()); - getModuleErrorWarnings(warnings, showAllWarnings); + addModuleErrorWarnings(warnings, showAllWarnings); - getProbableLeakCountWarnings(warnings, showAllWarnings); + addProbableLeakCountWarnings(warnings, showAllWarnings); - getWebSocketConnectionWarnings(warnings, showAllWarnings); + addWebSocketConnectionWarnings(warnings, showAllWarnings); - getDbSchemaWarnings(warnings, showAllWarnings); + addDbSchemaWarnings(warnings, showAllWarnings); - getPasswordRuleWarnings(warnings, showAllWarnings); + addPasswordRuleWarnings(warnings, showAllWarnings); - getDeprecatedFeatureWarnings(warnings, showAllWarnings); + addDeprecatedFeatureWarnings(warnings, showAllWarnings); } // Issue 50015 - only show upgrade message to full site admins @@ -185,7 +185,7 @@ else if (showAllWarnings) private static final int MAX_SCHEMA_PROBLEMS_TO_SHOW = 3; - private void getDbSchemaWarnings(Warnings warnings, boolean showAllWarnings) + private void addDbSchemaWarnings(Warnings warnings, boolean showAllWarnings) { Map> schemaProblems = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); schemaProblems.putAll(_dbSchemaWarnings); @@ -216,13 +216,13 @@ private void getDbSchemaWarnings(Warnings warnings, boolean showAllWarnings) } } - private void getPasswordRuleWarnings(Warnings warnings, boolean showAllWarnings) + private void addPasswordRuleWarnings(Warnings warnings, boolean showAllWarnings) { if (showAllWarnings || (!AppProps.getInstance().isDevMode() && DbLoginService.get().getPasswordRule().isDeprecated())) warnings.add(HtmlString.of("Database authentication is configured with \"" + DbLoginService.get().getPasswordRule().name() + "\" strength, which is not appropriate for production deployments. This option will be removed in the next major release.")); } - private void getHeapSizeWarnings(Warnings warnings, boolean showAllWarnings) + private void addHeapSizeWarnings(Warnings warnings, boolean showAllWarnings) { // Issue 9683 - show admins warning about inadequate heap size (< 2GB) MemoryMXBean membean = ManagementFactory.getMemoryMXBean(); @@ -239,7 +239,7 @@ private void getHeapSizeWarnings(Warnings warnings, boolean showAllWarnings) } // Warn if running in production mode with an inadequate labkey db connection pool size - private void getConnectionPoolSizeWarnings(Warnings warnings, DbScope labkeyScope, boolean showAllWarnings) + private void addConnectionPoolSizeWarnings(Warnings warnings, DbScope labkeyScope, boolean showAllWarnings) { if (showAllWarnings || !AppProps.getInstance().isDevMode()) { @@ -256,7 +256,7 @@ else if (showAllWarnings || maxTotal < 20) } } - private void getJavaWarnings(Warnings warnings, boolean showAllWarnings) + private void addJavaWarnings(Warnings warnings, boolean showAllWarnings) { if (showAllWarnings || ModuleLoader.getInstance().getJavaVersion().isDeprecated()) { @@ -294,7 +294,7 @@ public static Set collectAllDeployedApps() return _deployedApps; } - private void getTomcatWarnings(Warnings warnings, boolean showAllWarnings) + private void addTomcatWarnings(Warnings warnings, boolean showAllWarnings) { if (showAllWarnings || ModuleLoader.getInstance().getTomcatVersion().isDeprecated()) { @@ -322,7 +322,7 @@ private void getTomcatWarnings(Warnings warnings, boolean showAllWarnings) } } - private void getModuleErrorWarnings(Warnings warnings, boolean showAllWarnings) + private void addModuleErrorWarnings(Warnings warnings, boolean showAllWarnings) { //module failures during startup--show to admins Map moduleFailures = ModuleLoader.getInstance().getModuleFailures(); @@ -347,13 +347,13 @@ private void getModuleErrorWarnings(Warnings warnings, boolean showAllWarnings) "schemas should be deleted via the ", "Module Details page", PageFlowUtil.urlProvider(AdminUrls.class).getModulesDetailsURL()); } - private void getWebSocketConnectionWarnings(Warnings warnings, boolean showAllWarnings) + private void addWebSocketConnectionWarnings(Warnings warnings, boolean showAllWarnings) { if (showAllWarnings || WebSocketConnectionManager.getInstance().showWarning()) addStandardWarning(warnings, "The WebSocket connection failed. LabKey Server uses WebSockets to send notifications and alert users when their session ends.", "configTomcat#websocket", "Tomcat Configuration"); } - private void getUserRequestedAdminOnlyModeWarnings(Warnings warnings, boolean showAllWarnings, boolean isSiteAdmin) + private void addUserRequestedAdminOnlyModeWarnings(Warnings warnings, boolean showAllWarnings, boolean isSiteAdmin) { //admin-only mode--show to admins if (showAllWarnings || AppProps.getInstance().isUserRequestedAdminOnlyMode()) @@ -363,7 +363,7 @@ private void getUserRequestedAdminOnlyModeWarnings(Warnings warnings, boolean sh } } - private void getProbableLeakCountWarnings(Warnings warnings, boolean showAllWarnings) + private void addProbableLeakCountWarnings(Warnings warnings, boolean showAllWarnings) { if (AppProps.getInstance().isDevMode()) { @@ -378,7 +378,7 @@ private void getProbableLeakCountWarnings(Warnings warnings, boolean showAllWarn } } - private void getDeprecatedFeatureWarnings(Warnings warnings, boolean showAllWarnings) + private void addDeprecatedFeatureWarnings(Warnings warnings, boolean showAllWarnings) { Collection flags = OptionalFeatureService.get().getOptionalFeatureFlags(OptionalFeatureService.FeatureType.Deprecated); List deprecated = flags.stream() From 1891f52676a973b8e69476ea88c3a01bbc34e58c Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Wed, 3 Dec 2025 13:44:58 -0800 Subject: [PATCH 2/3] Log deprecated Java versions. More consistent messaging between untested & deprecated versions. --- api/src/org/labkey/api/module/ModuleLoader.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/api/src/org/labkey/api/module/ModuleLoader.java b/api/src/org/labkey/api/module/ModuleLoader.java index 49d5743d602..971d0851b17 100644 --- a/api/src/org/labkey/api/module/ModuleLoader.java +++ b/api/src/org/labkey/api/module/ModuleLoader.java @@ -1386,8 +1386,17 @@ private void setJavaVersion() { _javaVersion = JavaVersion.get(); + final String message; + if (!_javaVersion.isTested()) - _log.warn("LabKey Server has not been tested against Java runtime version {}.", JavaVersion.getJavaVersionDescription()); + message = "has not been tested with LabKey Server"; + else if (_javaVersion.isDeprecated()) + message = "is no longer supported"; + else + message = null; + + if (message != null) + _log.warn("The deployed version of Java, {}, {}. We recommend installing {}.", JavaVersion.getJavaVersionDescription(), message, JavaVersion.getRecommendedJavaVersion()); } public JavaVersion getJavaVersion() From afe7976015c7b3fa1680f36a1f234b925fdd22aa Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Wed, 3 Dec 2025 14:04:11 -0800 Subject: [PATCH 3/3] More succinct --- api/src/org/labkey/api/module/ModuleLoader.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/api/src/org/labkey/api/module/ModuleLoader.java b/api/src/org/labkey/api/module/ModuleLoader.java index 971d0851b17..444d2d2aef8 100644 --- a/api/src/org/labkey/api/module/ModuleLoader.java +++ b/api/src/org/labkey/api/module/ModuleLoader.java @@ -1386,17 +1386,15 @@ private void setJavaVersion() { _javaVersion = JavaVersion.get(); - final String message; - if (!_javaVersion.isTested()) - message = "has not been tested with LabKey Server"; + logJavaWarning("has not been tested with LabKey Server"); else if (_javaVersion.isDeprecated()) - message = "is no longer supported"; - else - message = null; + logJavaWarning("is no longer supported"); + } - if (message != null) - _log.warn("The deployed version of Java, {}, {}. We recommend installing {}.", JavaVersion.getJavaVersionDescription(), message, JavaVersion.getRecommendedJavaVersion()); + private void logJavaWarning(String message) + { + _log.warn("The deployed version of Java, {}, {}. We recommend installing {}.", JavaVersion.getJavaVersionDescription(), message, JavaVersion.getRecommendedJavaVersion()); } public JavaVersion getJavaVersion()