diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 17ec55d4ca..c3cc6936d8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -38,6 +38,8 @@ The build is driven by Gradle through the included wrapper; no separate Gradle i
```
On Windows use `gradlew.bat` instead of `./gradlew`. The assembled distribution lands in `server/setup`, the same location the previous Ant build used. For release artifacts, run a clean build: `./gradlew clean build dist`. Windows with SDKMan may generate an error about the file path being too long in the javadoc step, skip this by adding `-x :server:userApiJavadoc` to your Gradle command.
+By default the build compiles and runs the tests with any Java 17 JDK Gradle finds installed, including those installed by SDKMAN. To use Java 21 instead, add `-PjavaToolchain=21`, or put `javaToolchain=21` in `~/.gradle/gradle.properties`. The compiled output still targets Java 17. Gradle does not download JDKs, so the version you name must already be installed.
+
Dependencies are pinned and checksum-verified. To change a dependency version: edit `gradle/libs.versions.toml`, then refresh the checksum metadata **with a cold dependency cache and CI's flags**:
```bash
GRADLE_USER_HOME=$(mktemp -d) ./gradlew --write-verification-metadata sha256 build dist -PdisableSigning=true -Pcoverage=true
diff --git a/build.gradle b/build.gradle
index 83d7e13a66..6f363be8d1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -34,6 +34,8 @@
* ./gradlew test [-Pcoverage=true] tests only (JaCoCo optional)
* ./gradlew dist distribution extension zips
* ./gradlew clean clean all modules
+ * ./gradlew build -PjavaToolchain=21 compile/test with another JDK
+ * (output still targets Java 17)
*
* For release artifacts run a clean build (./gradlew clean build dist):
* the staging into server/setup removes stale files where it owns the
@@ -71,6 +73,9 @@ ext {
disableTests = flag('disableTests')
disableSigning = flag('disableSigning')
coverageEnabled = flag('coverage')
+ // the shipped bytecode and API level; the JDK used to build may be newer
+ javaRelease = 17
+ javaToolchain = (providers.gradleProperty('javaToolchain').getOrNull() ?: javaRelease) as int
}
allprojects {
@@ -158,7 +163,7 @@ subprojects {
java {
toolchain {
- languageVersion = JavaLanguageVersion.of(17)
+ languageVersion = JavaLanguageVersion.of(rootProject.javaToolchain)
}
}
@@ -177,6 +182,7 @@ subprojects {
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
+ options.release = rootProject.javaRelease
options.debug = true
}
// Match Ant's javac invocation: -sourcepath defaults to srcdir, and
@@ -275,7 +281,7 @@ subprojects {
if (rootProject.coverageEnabled) {
apply plugin: 'jacoco'
- jacoco { toolVersion = '0.8.8' }
+ jacoco { toolVersion = '0.8.15' }
tasks.withType(Test).configureEach { finalizedBy tasks.named('jacocoTestReport') }
tasks.named('jacocoTestReport') {
reports.xml.required = true
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index a55f913c97..f954bcabb3 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -2533,41 +2533,41 @@
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
@@ -2858,12 +2858,12 @@
-
-
-
+
+
+
-
-
+
+
@@ -2874,14 +2874,6 @@
-
-
-
-
-
-
-
-
@@ -2890,12 +2882,17 @@
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
@@ -2906,12 +2903,12 @@
-
-
-
+
+
+
-
-
+
+
diff --git a/server/build.gradle b/server/build.gradle
index d928023bb5..f9855c247f 100644
--- a/server/build.gradle
+++ b/server/build.gradle
@@ -40,16 +40,6 @@ def syncDonkeyLibs = tasks.register('syncDonkeyLibs', Sync) {
compileJava.dependsOn syncDonkeyLibs
-compileTestJava {
- options.compilerArgs += [
- '--add-modules=java.sql.rowset',
- '--add-exports=java.sql.rowset/com.sun.rowset=ALL-UNNAMED',
- '--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED',
- '--add-exports=java.base/sun.security.provider=ALL-UNNAMED',
- ]
-}
-
-
def generateVersionProperties = tasks.register('generateVersionProperties') {
description = 'Generates version.properties (embedded in mirth-client-core.jar).'
def outFile = file('version.properties')
@@ -502,9 +492,12 @@ def userApiJavadoc = tasks.register('userApiJavadoc') {
})
outputs.dir outDir
dependsOn syncDonkeyLibs
+ def javadocTool = javaToolchains.javadocToolFor(java.toolchain)
+ // the output depends on the javadoc version, which is not otherwise an input
+ inputs.property('javadocVersion', javadocTool.map { it.metadata.languageVersion.asInt() })
doLast {
outDir.mkdirs()
- def cmd = [new File(System.getProperty('java.home'), 'bin/javadoc').absolutePath,
+ def cmd = [javadocTool.get().executablePath.asFile.absolutePath,
'-d', outDir.absolutePath,
'-notimestamp',
'-classpath', (configurations.compileClasspath + fileTree(dir: 'lib', include: '**/*.jar')).asPath,
diff --git a/server/src/test/java/com/mirth/commons/encryption/test/KeyEncryptorTest.java b/server/src/test/java/com/mirth/commons/encryption/test/KeyEncryptorTest.java
index a2d0f12763..28bc97bd90 100644
--- a/server/src/test/java/com/mirth/commons/encryption/test/KeyEncryptorTest.java
+++ b/server/src/test/java/com/mirth/commons/encryption/test/KeyEncryptorTest.java
@@ -35,10 +35,12 @@
import com.mirth.commons.encryption.Output;
import com.mirth.commons.encryption.util.EncryptionUtil;
import com.mirth.connect.model.EncryptionSettings;
-import com.sun.crypto.provider.SunJCE;
public class KeyEncryptorTest {
+ // a name, not a class literal: java.base does not export this package
+ private static final String SUN_JCE_PROVIDER = "com.sun.crypto.provider.SunJCE";
+
@Test
public void testAESCBC128BC() throws Exception {
EncryptionSettings encryptionSettings = new EncryptionSettings();
@@ -65,7 +67,7 @@ public void testAESCBC128SunJCE() throws Exception {
EncryptionSettings encryptionSettings = new EncryptionSettings();
encryptionSettings.setEncryptionAlgorithm("AES/CBC/PKCS5Padding");
encryptionSettings.setEncryptionKeyLength(128);
- encryptionSettings.setSecurityProvider(SunJCE.class.getName());
+ encryptionSettings.setSecurityProvider(SUN_JCE_PROVIDER);
encryptionSettings.setEncryptionCharset(StandardCharsets.UTF_8.name());
testEncryptAndDecrypt(encryptionSettings);
}
@@ -76,7 +78,7 @@ public void testAESCBC128SunJCE() throws Exception {
// EncryptionSettings encryptionSettings = new EncryptionSettings();
// encryptionSettings.setEncryptionAlgorithm("AES/CBC/PKCS5Padding");
// encryptionSettings.setEncryptionKeyLength(256);
-// encryptionSettings.setSecurityProvider(SunJCE.class.getName());
+// encryptionSettings.setSecurityProvider(SUN_JCE_PROVIDER);
// encryptionSettings.setEncryptionCharset(StandardCharsets.UTF_8.name());
// testEncryptAndDecrypt(encryptionSettings);
// }
@@ -161,7 +163,7 @@ public void testAESCBC128SunJCE_AESGCM128BC() throws Exception {
EncryptionSettings oldEncryptionSettings = new EncryptionSettings();
oldEncryptionSettings.setEncryptionAlgorithm("AES/CBC/PKCS5Padding");
oldEncryptionSettings.setEncryptionKeyLength(128);
- oldEncryptionSettings.setSecurityProvider(SunJCE.class.getName());
+ oldEncryptionSettings.setSecurityProvider(SUN_JCE_PROVIDER);
oldEncryptionSettings.setEncryptionCharset(StandardCharsets.UTF_8.name());
EncryptionSettings encryptionSettings = new EncryptionSettings();
@@ -225,7 +227,7 @@ public void testDESCBC56SunJCE() throws Exception {
EncryptionSettings encryptionSettings = new EncryptionSettings();
encryptionSettings.setEncryptionAlgorithm("DES/CBC/PKCS5Padding");
encryptionSettings.setEncryptionKeyLength(56);
- encryptionSettings.setSecurityProvider(SunJCE.class.getName());
+ encryptionSettings.setSecurityProvider(SUN_JCE_PROVIDER);
encryptionSettings.setEncryptionCharset(StandardCharsets.UTF_8.name());
testEncryptAndDecrypt(encryptionSettings);
}