January 18, 2026
Spring Boot + Spring AI: Mastering Intelligent Application Development
Building AI-powered features used to mean juggling SDKs, HTTP clients, and prompt logic scattered across your codebase. With Spring AIβ¦

By Umesh Kumar Yadav
3 min read
Building AI-powered features used to mean juggling SDKs, HTTP clients, and prompt logic scattered across your codebase. With Spring AI, that story changes. When combined with Spring Boot, you get a clean, production-ready way to add large language model (LLM) capabilities directly into your Java applications.
In this article, we'll walk through a simple but realistic Spring Boot + Spring AI project, explain the key ideas, and then explore advanced features and future trends.
I. Introduction
Spring Boot
Spring Boot is the backbone of modern Java backend development. It simplifies Spring applications by providing:
- Auto-configuration
- Embedded servers like Tomcat
- A strong "convention over configuration" philosophy
The result is simple: you can build standalone, production-grade applications with minimal setup.
Spring AI
Spring AI is a newer module in the Spring ecosystem that focuses on AI integration. Its goal is to provide a unified abstraction layer over popular AI services, such as OpenAI, Azure OpenAI, and Hugging Face.
Instead of dealing with raw HTTP calls or vendor-specific SDKs, you work with familiar Spring concepts like clients, templates, and configuration properties.
II. Implementation Details
A Simple Spring Boot + Spring AI Application
Let's build a minimal AI-powered REST service step by step.
1. Environmental Preparation
Before you start, make sure you have:
- JDK 17+
- Maven 3.6+
- An OpenAI API Key (from platform.openai.com)
2. Project Initialization
You can generate the project using start.spring.io with these dependencies:
- Spring Web
- Spring AI (OpenAI starter)
Or add them directly to pom.xml:
<!-- Spring AI OpenAI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>0.8.1</version>
</dependency>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- Spring AI OpenAI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>0.8.1</version>
</dependency>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>This starter hides most of the boilerplate and gives you a ready-to-use AI client.
3. Configure the OpenAI API Key
In application.properties or application.yml, configure your API key and model:
spring.ai.openai.api-key=your-api-key-here
spring.ai.openai.chat.options.model=gpt-3.5-turbospring.ai.openai.api-key=your-api-key-here
spring.ai.openai.chat.options.model=gpt-3.5-turboSpring Boot will automatically wire everything for you.
4. Create a Simple Controller
Now let's expose a basic chat endpoint.
import org.springframework.ai.chat.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AIController {
private final ChatClient chatClient;
public AIController(ChatClient chatClient) {
this.chatClient = chatClient;
}
@GetMapping("/ai/chat")
public String chat(@RequestParam String message) {
return chatClient.call(message);
}
}import org.springframework.ai.chat.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AIController {
private final ChatClient chatClient;
public AIController(ChatClient chatClient) {
this.chatClient = chatClient;
}
@GetMapping("/ai/chat")
public String chat(@RequestParam String message) {
return chatClient.call(message);
}
}This is the beauty of Spring AI: a single method call sends the prompt to the model and returns the response.
5. Advanced: Custom Prompt Templates
For real applications, plain text prompts are often not enough. Spring AI provides PromptTemplate to create structured, reusable prompts.
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@PostMapping("/ai/translate")
public String translate(@RequestBody TranslationRequest request) {
PromptTemplate promptTemplate = new PromptTemplate("""
Translate the following {sourceLang} text into {targetLang}:
{text}
""");
promptTemplate.add("sourceLang", request.sourceLang());
promptTemplate.add("targetLang", request.targetLang());
promptTemplate.add("text", request.text());
return chatClient.call(promptTemplate.render());
}
record TranslationRequest(String sourceLang, String targetLang, String text) {}import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@PostMapping("/ai/translate")
public String translate(@RequestBody TranslationRequest request) {
PromptTemplate promptTemplate = new PromptTemplate("""
Translate the following {sourceLang} text into {targetLang}:
{text}
""");
promptTemplate.add("sourceLang", request.sourceLang());
promptTemplate.add("targetLang", request.targetLang());
promptTemplate.add("text", request.text());
return chatClient.call(promptTemplate.render());
}
record TranslationRequest(String sourceLang, String targetLang, String text) {}This approach makes prompts easier to read, maintain, and extend.
6. Run the Application
Start the application using your IDE or the command line:
mvn spring-boot:runmvn spring-boot:runThe embedded server will start on port 8080.
7. Interface Testing
1) /ai/chat
Request:
GET http://localhost:8080/ai/chat?message=JavaδΈHello WorldGET http://localhost:8080/ai/chat?message=JavaδΈHello WorldResponse:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}2) /ai/translate
Request (POST):
{
"sourceLang": "Chinese",
"targetLang": "English",
"text": "The weather is really nice today"
}{
"sourceLang": "Chinese",
"targetLang": "English",
"text": "The weather is really nice today"
}Response:
"Today's weather is really nice.""Today's weather is really nice."8. Advanced Configuration
You can fine-tune model behavior using configuration options:
spring.ai.openai.chat.options.temperature=0.7
spring.ai.openai.chat.options.max-tokens=500spring.ai.openai.chat.options.temperature=0.7
spring.ai.openai.chat.options.max-tokens=500- temperature controls randomness
- max-tokens limits response length
9. Exception Handling
A global exception handler keeps error handling clean and consistent.
import org.springframework.ai.openai.api.OpenAiApiException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(OpenAiApiException.class)
public ResponseEntity<String> handleOpenAiError(OpenAiApiException ex) {
return ResponseEntity
.status(ex.getStatusCode())
.body("AI Exception: " + ex.getMessage());
}
}import org.springframework.ai.openai.api.OpenAiApiException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(OpenAiApiException.class)
public ResponseEntity<String> handleOpenAiError(OpenAiApiException ex) {
return ResponseEntity
.status(ex.getStatusCode())
.body("AI Exception: " + ex.getMessage());
}
}10. Complete Project Structure
src/main/java
βββ com.example.aiapp
βββ AIController.java
βββ GlobalExceptionHandler.java
βββ AiAppApplication.javasrc/main/java
βββ com.example.aiapp
βββ AIController.java
βββ GlobalExceptionHandler.java
βββ AiAppApplication.java11. Key Points Explained
- Dependency management: Spring AI starters simplify setup
- Auto-configuration:
ChatClientis injected automatically - Prompt templates: Clean, structured prompt generation
- Scalability: Easy to switch AI providers later
III. Expansion
1. Error Scenarios
Invalid API key:
{
"status": 401,
"error": "Unauthorized",
"message": "AI: Invalid API Key"
}{
"status": 401,
"error": "Unauthorized",
"message": "AI: Invalid API Key"
}Other common cases include missing fields or unsupported languages.
2. Output May Differ
AI output is probabilistic. Different models or temperature values can produce slightly different results, even for the same prompt.
3. Streaming Responses (Advanced)
For real-time output, similar to ChatGPT typing, use streaming:
@GetMapping("/ai/chat-stream")
public Flux<String> chatStream(@RequestParam String message) {
return streamingChatClient.stream(message);
}@GetMapping("/ai/chat-stream")
public Flux<String> chatStream(@RequestParam String message) {
return streamingChatClient.stream(message);
}4. Processing Extremely Long Texts
If responses are truncated, increase token limits:
spring.ai.openai.chat.options.max-tokens=2000spring.ai.openai.chat.options.max-tokens=20005. Custom Response Formats
To return JSON instead of plain text:
@PostMapping(value = "/ai/translate", produces = "application/json")
public Map<String, String> translate(...) {
return Map.of("result", translatedText);
}@PostMapping(value = "/ai/translate", produces = "application/json")
public Map<String, String> translate(...) {
return Map.of("result", translatedText);
}Response:
{ "result": "Today's weather is really nice." }{ "result": "Today's weather is really nice." }6. Additional Testing Ideas
- Ask for algorithms:
Write a Fibonacci sequence function in Python- Translate into different languages:
{
"sourceLang": "English",
"targetLang": "French",
"text": "Hello, how are you?"
}{
"sourceLang": "English",
"targetLang": "French",
"text": "Hello, how are you?"
}Expected output:
"Bonjour, comment allez-vous ?""Bonjour, comment allez-vous ?"IV. Summary and Trends
Spring Boot remains the foundation for Java backend development, while Spring AI adds a powerful AI layer on top. Together, they enable a "traditional business + AI enhancement" architecture, suitable for chatbots, document analysis, code generation, and more.
Future Trends
1. Technical Direction
- Multimodal support (text, images, speech, video)
- Better local model integration (Llama, Ollama)
- Faster, more efficient streaming responses
2. Ecosystem Expansion
- Support for more AI providers (Gemini, Claude)
- Deep integration with Spring Security and Spring Cloud
- Enterprise-ready features like rate limiting and monitoring
3. Industry Applications
- Vertical solutions for finance, healthcare, and education
- AI Agent frameworks for autonomous task execution
π Thanks for reading.
- If you enjoyed this article, please consider giving it a clap.π
- I would appreciate hearing your thoughts in the comments below! π
- Follow me for ongoing learning and connection!π