# getting-started Companion code for [Spring AI 2.0 in 10 Minutes: ChatClient on Spring Boot 4.1](https://ankurm.com/spring-ai-2-0-chatclient-boot-4-1/) on [ankurm.com](https://ankurm.com). One `ChatClient` bean, three endpoints, and a test that proves `spring.ai.model.chat` switches the provider without touching either. The deeper walkthrough (what each test caught, the API references) lives in the article's accordion sections, not in this README -- see the versions callout and the "going deeper" list at the end of each section. ## Versions | Component | Version | |---|---| | Spring Boot | 4.1.1 | | Spring AI | 2.0.1 | | Java | 25 (LTS) | ## Quickstart ```bash mvn -o test # runs against a scripted ChatModel, no key needed, ~10s OPENAI_API_KEY=sk-... ./scripts/run.sh # the real app, port 8080 ``` ## Endpoints | Method | Path | What it shows | |---|---|---| | GET | `/api/chat?message=` | `ChatClient.prompt().user(...).call().content()` | | GET | `/api/chat/as?voice=&message=` | a templated system prompt filled via `.param(...)` | | GET | `/api/chat/stream?message=` | `.stream().content()`, a `Flux` | ## Switching providers One property, no code change: ```properties spring.ai.model.chat=openai # org.springframework.ai.openai.OpenAiChatModel spring.ai.model.chat=ollama # org.springframework.ai.ollama.OllamaChatModel ``` `ProviderSwitchTest` proves this mechanically -- it never calls either provider's server, only inspects which `ChatModel` bean class the Spring context assembled under each property value. ## Output | File | Regenerated by | |---|---| | `output/01-plain-call.txt` | `ChatClientEndpointsTest` | | `output/02-system-template.txt` | `ChatClientEndpointsTest` | | `output/03-streaming.txt` | `ChatClientEndpointsTest` | | `output/04-provider-switch.txt` | `ProviderSwitchTest` | | `output/05-real-network-round-trip.txt` | captured manually against the real OpenAI API; see its own header | `scripts/run-all.sh` regenerates 01-04. 05 is not part of that script -- it needs a live network path and a real (even if invalid) key, and is included once as evidence that the wiring reaches OpenAI's own server.