Bump project to Java 17#779
Merged
donald-pinckney merged 2 commits intomainfrom May 1, 2026
Merged
Conversation
The springai sample modules require Java 17 (Spring AI 1.1 needs Spring Boot 3.x, which needs Java 17). Running spotlessCheck on Java 11 made google-java-format choke on text blocks in those sources with "unclosed string literal" errors. Bump the format job's setup-java to 17 so it can parse the springai sources. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spring AI requires Java 17, but parts of the build (CI Docker image, root Java target, format-job JDK) were still pinned to Java 11. The follow-on for the spring-ai work was a partial bump that only fixed the format job. This finishes the bump everywhere: - docker/github/Dockerfile: eclipse-temurin:11-focal -> :17-jammy. This is the image the unittest CI job runs ./gradlew test inside. - build.gradle: drop the Spring-Boot-version-conditional Java target (Spring Boot 2.7 runs fine on Java 17, so there's no reason to pin source/target compatibility to 11). - springboot-basic/build.gradle: drop a dead isJava11Compatible() branch (both arms were identical). - ci.yml: keep Java 17 for the format job; clean up the inline comment that framed it as a springai-only exception. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
maciejdudko
approved these changes
May 1, 2026
donald-pinckney
added a commit
that referenced
this pull request
May 1, 2026
Adds Spring AI to the module list at the top, describes the four nested samples (basic, mcp, multimodel, rag) under a new "Running Spring AI Samples" section, and consolidates the per-sample Java version notes into a single "Java 17+ for all samples" line now that #779 bumped the project-wide target. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
donald-pinckney
added a commit
that referenced
this pull request
May 1, 2026
* Spring AI samples
* Fix sample configs and remove runtimeOnly workarounds
- Remove runtimeOnly spring-ai-rag and spring-ai-mcp from shared
config (no longer needed after T6 plugin split in sdk-java)
- Fix workflow class package references (old prototype packages)
- Add web-application-type: none to RAG and multimodel configs
- Exclude conflicting chat auto-configs in multimodel sample
All 5 samples now boot successfully against a Temporal dev server.
MCP sample requires Node.js/npx for the MCP server.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update samples for T15: remove @DeterministicTool and sandboxing sample
- StringTools: remove @DeterministicTool (plain tools run in workflow
context by default now)
- Delete springai-sandboxing sample (SandboxingAdvisor removed from SDK)
- Update comments referencing @DeterministicTool
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Clean up Spring AI samples PR for merge
- Remove committed build/ directories and add them to .gitignore.
- Gate includeBuild('../sdk-java') on sibling checkout existence so the
build works out-of-the-box when the springai samples are not being
touched (and will resolve cleanly once temporal-spring-ai publishes).
- core: pin io.grpc:grpc-util version explicitly and switch the SSL sample
to AdvancedTlsX509KeyManager.updateIdentityCredentials (non-deprecated
API) to fix compilation under -Werror with the composite-build grpc.
- springai-multimodel: fix doc mismatch on model names, route unprefixed
input to the "default" model, drop hard-coded model-version hints from
system prompts.
- springai-rag: correct Javadoc to match actual code (no EmbeddingModelActivity),
accept bare "ask" as a usage-prompt trigger, normalize text block indentation.
- springai-mcp: fix advisor name comment, normalize text block indentation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Use mavenLocal for temporal-spring-ai instead of composite build
Replace the includeBuild('../sdk-java') dependency-substitution block with
a plain mavenLocal() repository and a pinned 1.35.0-SNAPSHOT coordinate for
the springai* samples. Build temporal-spring-ai locally with
`./gradlew publishToMavenLocal` in an sdk-java checkout and the samples
pick it up via mavenLocal — no composite build, no SDK-wide substitution.
A nice side-effect: the core module no longer has a newer grpc forced onto
its classpath, so the SSL sample's gRPC workarounds (explicit grpc-util
dep + updateIdentityCredentials switch) are no longer needed. Revert them.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add TASK_QUEUE.json tracking remaining PR work
Tracks the mavenLocal workaround unwind (blocked on temporal-spring-ai
publishing) and unaddressed reviewer threads. Delete before merge.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Updated after changes to Spring AI
* Add snipsync markers to Spring AI samples
Wraps natural snippet boundaries in the spring-ai samples so the
docs/spring-ai-integration page can pull canonical code via snipsync
instead of carrying inline copies. Six markers added:
- samples-java-spring-ai-chat-workflow-init: ChatWorkflowImpl @WorkflowInit
- samples-java-spring-ai-activity-tool: WeatherActivity interface
- samples-java-spring-ai-side-effect-tool: TimestampTools class
- samples-java-spring-ai-plain-tool: StringTools class
- samples-java-spring-ai-per-model-options: ChatModelConfig per-model bean
- samples-java-spring-ai-provider-options: MultiModelWorkflowImpl think route
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* spring-ai samples: pin to released temporal-spring-ai 1.35.0
temporal-spring-ai is now on Maven Central. Drop the mavenLocal()
repository and the SNAPSHOT pin that were bridging the gap; the
springai* samples now resolve from mavenCentral like everything else.
springAiSdkVersion stays separate from javaSDKVersion because the
spring-ai module requires a newer SDK than the rest of the samples
currently pin.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Group spring-ai samples under a single springai/ directory
Moves the four spring-ai sample modules from top-level peers into
nested subprojects of springai/, so the repo root has one springai/
instead of four (springai, springai-mcp, springai-multimodel,
springai-rag). Each module keeps its own build.gradle and Spring Boot
entry point — only the directory layout and Gradle project paths
change. Invocations become :springai:basic, :springai:mcp, etc.
Also folds in the earlier simplification: now that javaSDKVersion is
1.35.0 globally, gradle/springai.gradle drops the separate
springAiSdkVersion variable and references the global one directly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* springai/mcp: await initialization in chat signal handler
Replaces the early-return-with-placeholder pattern in McpWorkflowImpl.chat()
with Workflow.await(() -> initialized). Signals can yield, so awaiting is
the idiomatic Temporal way to handle "operation arrived before init
finished" — the client's signal RPC has already returned, and the
workflow-side handling just resumes once run() completes MCP tool
discovery and finishes building the chat client.
listTools() stays placeholder-based because it's a @QueryMethod and
queries cannot yield.
Addresses brianstrauch review comment on PR #775.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* springai/multimodel: drop redundant default: CLI prefix
The CLI exposed both `default:` and `openai:` prefixes, which both
ended up calling OpenAI — ChatModelConfig declares @primary on
openAiChatModel, so ActivityChatModel.forDefault() resolves to it.
Reviewers reasonably found this confusing.
Drop the explicit `default:` prefix; route no-prefix input to the
"default" workflow client instead. The chatClients entry stays so
the sample still demonstrates both forDefault() (@primary resolution)
and forModel(name) (explicit lookup) — added a comment block at the
registration site explaining that the dual entry is intentional.
Addresses brianstrauch review comment on PR #775.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* springai/rag: show usage when add/search are typed without args
Reviewer noted that bare `ask` falls through to printing usage but
bare `add` or `search` did not — the startsWith check required a
trailing space. Apply the same equals|startsWith pattern that the
ask branch already uses, with a length guard around the substring.
Addresses brianstrauch review comment on PR #775.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add ai-sdk to CODEOWNERS for springai
* springai/multimodel: include "think" in chat() javadoc model names
The javadoc listed "openai", "anthropic", "default" but the workflow
also accepts "think" (Anthropic with extended thinking enabled).
Add it to the @param doc so users don't send a name and wonder why
it falls through to the unknown-model branch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* springai/basic: explain why run()'s systemPrompt parameter is unused
@WorkflowInit requires the constructor and the @WorkflowMethod to
share a parameter list, so run(String) must take systemPrompt even
though only the constructor uses it. Add a comment so readers don't
trip over the apparent unused parameter (and so static analyzers
that flagged it have an explanation in-source).
Addresses Copilot review on PR #775.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* gradle/springai: document the Spring Boot plugin/BOM version skew
The root build.gradle pins the Spring Boot Gradle plugin at
springBootPluginVersion (2.7.13) for the legacy springboot/ samples,
while Spring AI 1.1.0 needs Spring Boot 3.5.x via BOM import. The
plugin and BOM are independent enough that this works in practice,
but a future reader (or static analyzer) reasonably gets confused.
Add a comment block explaining the trade-off and naming the two
follow-up paths that would actually fix it (move plugin out of root
plugins block, or migrate legacy springboot/ to 3.x).
Addresses Copilot review on PR #775.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* .gitignore: collapse per-module build/out entries into globs
Replaces twelve explicit per-module entries (/build, /core/build,
/springai/basic/build, ...) with two globs (**/build/, **/out/) so
new sample modules don't need a .gitignore edit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* README: document Spring AI samples and Java 17 requirement
Adds Spring AI to the module list at the top, describes the four
nested samples (basic, mcp, multimodel, rag) under a new "Running
Spring AI Samples" section, and consolidates the per-sample Java
version notes into a single "Java 17+ for all samples" line now
that #779 bumped the project-wide target.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* springai samples: address Copilot review nits
Five small fixes flagged in PR #775 review:
- Rename springai/basic/src/main/resources/application.yml to .yaml
to match the convention used by every other sample in the repo.
- Fix the @code ./gradlew :example-* paths in McpApplication,
RagApplication, and MultiModelApplication javadocs to the actual
module paths (:springai:mcp, :springai:rag, :springai:multimodel).
- Add spring.main.web-application-type: none to springai/mcp's
application.yaml. The module pulls in spring-boot-starter-webflux
which would otherwise spin up a reactive web server we don't want.
Matches the other three springai samples.
- Drop stale references to EmbeddingModelActivity from the
RagApplication javadoc and startup banner. The sample uses
VectorStoreActivity exclusively; embeddings are produced inside
the configured Spring AI VectorStore, not via a separate activity.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Untrack .vscode/ IDE settings
Slipped into the previous commit via git add -A. .vscode/ is
per-developer IDE config — add to .gitignore.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* undo gitignore change
* springai/multimodel: use LinkedHashMap for chatClients
The unknown-model error message renders chatClients.keySet() into
lastResponse, which is workflow state. HashMap iteration order isn't
guaranteed across JVMs, so a replay on a different worker could
produce a different rendered string and surface as a non-determinism
error. LinkedHashMap iterates in insertion order, which is
deterministic regardless of JVM.
Addresses Copilot review on PR #775.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* springai/rag: capture lastResponse before signaling, not after
waitForResponse() previously read getLastResponse() *after* the
signal had been sent. If the workflow processed the signal between
the signal call and the first poll, the captured baseline was
already the new response and the loop waited for a second change
that never came, then timed out.
Fix matches the pattern McpApplication uses: capture
previousResponse before the signal, pass it into waitForResponse,
and poll for a value different from that pre-signal baseline.
Addresses Copilot review on PR #775.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* springai/multimodel: capture previous response before signaling
Same bug pattern that RagApplication had: the polling loop compared
against an empty-string baseline, so the very first poll could
return the stale prior response and print it as if it were the new
one. Capture previousResponse before sending the chat signal and
wait until getLastResponse() differs from that pre-signal baseline.
Also drop the redundant initial Thread.sleep(100) — the loop's own
sleep handles backoff, and reading immediately is fine when we're
comparing against the pre-signal baseline.
Addresses Copilot review on PR #775.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Remove TASK_QUEUE.json
Internal tracking file scoped to PR #775. All listed tasks and
review threads have been resolved or replied to; the file's job
is done.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Update README.md
Co-authored-by: Maciej Dudkowski <maciej.dudkowski@temporal.io>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Maciej Dudkowski <maciej.dudkowski@temporal.io>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Spring AI work surfaced that the project's CI and build settings still pinned Java 11 in several places. This PR moves to Java 17 everywhere:
docker/github/Dockerfile:eclipse-temurin:11-focal→:17-jammy(image used by the unittest CI job)build.gradle: drop the Spring-Boot-version-conditional Java target (Spring Boot 2.7 runs on Java 17 fine)springboot-basic/build.gradle: drop a deadisJava11Compatible()branch with identical armsci.yml: keep Java 17 on the Code format job (cherry-picked from the in-flight Spring AI samples PR), clean up the inline comment that framed it as a springai-only exceptionSplit out from #775 so the Java-version bump can be reviewed independently.
Test plan
./gradlew clean spotlessCheck compileJavapasses locally