Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,13 @@ jobs:
USER: unittest
TEMPORAL_SERVICE_ADDRESS: localhost:7233
USE_DOCKER_SERVICE: true
run: ./gradlew --no-daemon test -x spotlessCheck -x spotlessApply -x spotlessJava
run: ./gradlew --no-daemon test -x spotlessCheck -x spotlessApply -x spotlessJava -x :temporal-spring-boot-autoconfigure-4:test -x :temporal-spring-boot-starter-4:test

- name: Run Jackson 3 converter tests
env:
USER: unittest
USE_DOCKER_SERVICE: false
run: ./gradlew --no-daemon :temporal-sdk:jackson3Tests -x spotlessCheck -x spotlessApply -x spotlessJava

- name: Run virtual thread tests
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
- name: Set up Java
uses: actions/setup-java@v5
with:
java-version: "11"
java-version: "17"
distribution: "temurin"

- name: Set up Gradle
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Set up Java
uses: actions/setup-java@v5
with:
java-version: '11'
java-version: '17'
distribution: 'temurin'

- name: Set up Gradle
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ src/main/idls/*
.project
.settings
.vscode/
*/bin
*/bin
/.claude
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ ext {
// Platforms
grpcVersion = '1.75.0' // [1.38.0,) Needed for io.grpc.protobuf.services.HealthStatusManager
jacksonVersion = '2.15.4' // [2.9.0,)
jackson3Version = '3.0.4'
nexusVersion = '0.4.0-alpha'
// we don't upgrade to 1.10.x because it requires kotlin 1.6. Users may use 1.10.x in their environments though.
micrometerVersion = project.hasProperty("edgeDepsTest") ? '1.13.6' : '1.9.9' // [1.0.0,)
Expand Down Expand Up @@ -57,6 +58,7 @@ ext {
// Spring Boot 3 requires Java 17, java-sdk builds against 2.x version because we support Java 8.
// We do test compatibility with Spring Boot 3 in integration tests.
springBootVersion = project.hasProperty("edgeDepsTest") ? '3.1.12' : '2.7.18'// [2.4.0,)
springBoot4Version = '4.0.2'

// test scoped
// we don't upgrade to 1.3 and 1.4 because they require slf4j 2.x
Expand Down
14 changes: 14 additions & 0 deletions gradle/linting.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,18 @@ subprojects {
}

classes.dependsOn 'spotlessApply'
}

// Format shared Spring Boot source files that live outside any Gradle subproject.
// Spotless requires targets to be within the project dir, so this must run at the root level.
if (file('temporal-spring-boot-shared/src').exists()) {
apply plugin: 'com.diffplug.spotless'
spotless {
java {
target fileTree('temporal-spring-boot-shared/src') { include '*/java/**/*.java' }
targetExclude '**/generated/*'
targetExclude '**/.idea/**'
googleJavaFormat('1.24.0')
}
}
}
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ include 'temporal-opentracing'
include 'temporal-kotlin'
include 'temporal-spring-boot-autoconfigure'
include 'temporal-spring-boot-starter'
include 'temporal-spring-boot-autoconfigure-4'
include 'temporal-spring-boot-starter-4'
include 'temporal-remote-data-encoder'
include 'temporal-shaded'
include 'temporal-workflowcheck'
Expand Down
2 changes: 2 additions & 0 deletions temporal-bom/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ dependencies {
api project(':temporal-shaded')
api project(':temporal-spring-boot-autoconfigure')
api project(':temporal-spring-boot-starter')
api project(':temporal-spring-boot-autoconfigure-4')
api project(':temporal-spring-boot-starter-4')
api project(':temporal-test-server')
api project(':temporal-testing')
api project(':temporal-envconfig')
Expand Down
99 changes: 99 additions & 0 deletions temporal-sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,13 @@ dependencies {

// Temporal SDK supports Java 8 or later so to support virtual threads
// we need to compile the code with Java 21 and package it in a multi-release jar.
// Similarly, Jackson 3 support requires Java 17+ and is compiled separately.
sourceSets {
java17 {
java {
srcDirs = ['src/main/java17']
}
}
java21 {
java {
srcDirs = ['src/main/java21']
Expand All @@ -47,9 +53,31 @@ sourceSets {
}

dependencies {
// The java17 source set needs protobuf and other main dependencies to compile. We pass
// the main compile classpath as files rather than extending from api/implementation
// configurations, because extendsFrom triggers Gradle's variant-aware resolution which
// rejects project dependencies when the java17 target JVM (17) differs from the resolved
// project's JVM compatibility (e.g. 21+ on CI edge runners).
java17Implementation files(sourceSets.main.output.classesDirs) { builtBy compileJava }
java17Implementation files({ sourceSets.main.compileClasspath })
java17CompileOnly "tools.jackson.core:jackson-databind:$jackson3Version"

java21Implementation files(sourceSets.main.output.classesDirs) { builtBy compileJava }
}

tasks.named('compileJava17Java') {
// Gradle toolchains are too strict and require the JDK to match the specified version exactly.
// This is a workaround to use a JDK 17+ compiler.
//
// See also: https://github.com/gradle/gradle/issues/16256
if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(17)
}
}
options.release = 17
}

tasks.named('compileJava21Java') {
// Gradle toolchains are too strict and require the JDK to match the specified version exactly.
// This is a workaround to use a JDK 21+ compiler.
Expand All @@ -64,6 +92,9 @@ tasks.named('compileJava21Java') {
}

jar {
into('META-INF/versions/17') {
from sourceSets.java17.output
}
into('META-INF/versions/21') {
from sourceSets.java21.output
}
Expand All @@ -72,6 +103,27 @@ jar {
)
}

// Publish Jackson 3 as an optional dependency so users can opt-in
afterEvaluate {
publishing {
publications {
mavenJava {
pom.withXml {
def depsNode = asNode()['dependencies'][0]
if (depsNode == null) {
depsNode = asNode().appendNode('dependencies')
}
def dep = depsNode.appendNode('dependency')
dep.appendNode('groupId', 'tools.jackson.core')
dep.appendNode('artifactId', 'jackson-databind')
dep.appendNode('version', '[' + jackson3Version + ',)')
dep.appendNode('optional', 'true')
}
}
}
}
}

task registerNamespace(type: JavaExec) {
getMainClass().set('io.temporal.internal.docker.RegisterTestNamespace')
classpath = sourceSets.test.runtimeClasspath
Expand All @@ -85,6 +137,22 @@ test {
}
}

// On Java 17+, prepend java17 classes to all test classpaths so that Class.forName finds
// the real Jackson3JsonPayloadConverter instead of the Java 8 stub. This lets us test
// the present-java17-but-absent-jackson3 behavior (NoClassDefFoundError) in the same
// test that tests the Java 8 stub behavior (UnsupportedOperationException).
tasks.withType(Test).configureEach {
if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) {
dependsOn compileJava17Java
}
doFirst {
int launcherMajorVersion = javaLauncher.get().metadata.languageVersion.asInt()
if (launcherMajorVersion >= 17) {
classpath = files(sourceSets.java17.output.classesDirs) + classpath
}
}
}

task testResourceIndependent(type: Test) {
useJUnit {
includeCategories 'io.temporal.worker.IndependentResourceBasedTests'
Expand Down Expand Up @@ -124,6 +192,36 @@ testing {
}
}

jackson3Tests(JvmTestSuite) {
dependencies {
// java17 output must come before project() (added by configureEach) so that
// the compiler and runtime see the real Jackson3JsonPayloadConverter — which
// has a wider API than the Java 8 stub (newDefaultJsonMapper, JsonMapper
// constructor) because the stub can't reference Jackson 3 types.
implementation files(sourceSets.java17.output.classesDirs) { builtBy compileJava17Java }
implementation "tools.jackson.core:jackson-databind:$jackson3Version"
}
targets {
all {
testTask.configure {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(17)
}
shouldRunAfter(test)
}
}
}
}

// Unlike virtualThreadTests, jackson3Tests source directly imports Jackson 3 types
// and java17 classes, so the compile task also needs a Java 17 compiler (not just
// the test launcher).
tasks.named('compileJackson3TestsJava') {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(17)
}
}

virtualThreadTests(JvmTestSuite) {
targets {
all {
Expand Down Expand Up @@ -164,5 +262,6 @@ testing {
}

tasks.named('check') {
dependsOn(testing.suites.jackson3Tests)
dependsOn(testing.suites.virtualThreadTests)
}
Loading
Loading