A minimal Spring Boot 3.5 app showcasing Spring AI ChatClient with OpenAI, prompt templates, and structured output conversion.
- Java 17+ (toolchain configured in
build.gradle) - Gradle Wrapper (use provided
gradlew.baton Windows) - An OpenAI-compatible API key
- Clone and enter the project directory.
- Set environment variables (temporary for current session):
$env:OPENAI_API_KEY = "your_openai_api_key"
# Optional: custom base URL (e.g., for Azure/OpenAI-compatible gateways)
$env:OPENAI_API_BASE_URL = "https://api.openai.com/v1"To persist for future sessions (requires new PowerShell after running):
setx OPENAI_API_KEY "your_openai_api_key"
setx OPENAI_API_BASE_URL "https://api.openai.com/v1"- Run the app:
./gradlew.bat bootRunThe app reads defaults from src/main/resources/application.properties.
Key properties (override via environment variables shown in braces):
spring.ai.openai.api-key=${OPENAI_API_KEY}spring.ai.openai.api-base-url=${OPENAI_API_BASE_URL:https://api.openai.com/v1}spring.ai.openai.default-model=gpt-5-nanospring.ai.openai.timeout=30sspring.ai.openai.max-tokens=2048
You can also package a runnable JAR:
./gradlew.bat clean build
java -jar build/libs/test-openai-0.0.1-SNAPSHOT.jar-
ChatController
GET /ai?message=...— simple text completionPOST /chat?message=...— simple text completion (POST)GET /stream?message=...— server-side streaming text
-
PromptController
GET /ai/prompt?message=...— send raw promptGET /ai/books/popular?genre=...— recommended books via inline templateGET /ai/test/system-prompt?message=...— uses system + user messagesGET /ai/books/popular/prompt-template?genre=...— usesprompts/books.st
-
OutputConverterController (structured output)
GET /ai/movies/artist/{actor}— string contentGET /ai/movies/artist/{actor}/list—List<String>usingListOutputConverterGET /ai/movies/artist/{actor}/map—Map<String,Object>viaMapOutputConverterGET /ai/movies/artist/{actor}/object—Movieobject viaBeanOutputConverter
-
OutputFluentController (fluent API + entity mapping)
GET /ai/movies-string— string content (Tom Hanks)GET /ai/movies—FilmographyentityGET /ai/movies-list—List<Filmography>for multiple actorsGET /ai/movies-by-actor?actor=...—Filmographyfor a given actor
-
PromptStuffController (prompt template + optional stuffing)
GET /ai/{city}/temprature?stuff=true|false— usesprompts/temprature.stand optionally includes example context fromprompts/temprature-example.txt
Static pages for quick manual testing:
GET /index.htmlGET /stream-index.html(basic streaming demo)
curl "http://localhost:8080/ai?message=Hello%20there"
curl -X POST "http://localhost:8080/chat?message=Tell%20me%20a%20joke"
curl "http://localhost:8080/stream?message=Write%20a%20short%20poem" --no-buffer
curl "http://localhost:8080/ai/books/popular?genre=fantasy"
curl "http://localhost:8080/ai/movies/artist/Tom%20Hanks/list"
curl "http://localhost:8080/ai/movies-by-actor?actor=Leonardo%20DiCaprio"
curl "http://localhost:8080/ai/London/temprature?stuff=true"controller— REST endpoints using Spring AIChatClientdto—Movie,Filmographymodels used by converters/entity mappingresources/prompts— prompt template files consumed by controllers
Run unit tests:
./gradlew.bat test- This project uses Spring AI BOM and
spring-ai-starter-model-openai. To switch providers, add the relevant starter and properties. - Windows users should prefer
./gradlew.batovergradlew.