Add AI to Your Java Project in Just a Few Lines with Spring AI 2.0
Spring AI 2.0 lets Java developers integrate large‑language‑model capabilities with minimal code by adding a starter, configuring model parameters, injecting a ChatClient bean, and optionally enabling Redis‑backed chat memory for multi‑turn conversations, all demonstrated with runnable examples and screenshots.
Spring AI Overview
Spring AI is an official Spring extension that abstracts AI model access, allowing developers to use familiar Spring patterns (starters, beans, dependency injection) to build AI‑enabled applications without dealing with low‑level HTTP or JSON handling.
Project Integration
Add the Spring AI BOM (version 2.0.0) to pom.xml to manage versions.
Include the OpenAI starter (compatible with DeepSeek) and the WebFlux starter for reactive streaming.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- Spring AI OpenAI Starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- SpringBoot WebFlux dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>Configure the model in application.yaml (using DeepSeek‑v4‑pro as an example).
spring:
ai:
openai:
# DeepSeek compatible endpoint
base-url: https://api.deepseek.com
api-key: ${DEEPSEEK_API_KEY}
chat:
model: deepseek-v4-proCreate a configuration class that defines a ChatClient bean.
@Configuration
public class SpringAIConfig {
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
return builder.build();
}
}Implementing Chat Functionality
A ChatController provides three endpoints: /chat/call – synchronous call using ChatClient.call(). /chat/stream – SSE streaming using ChatClient.stream() and returning MediaType.TEXT_EVENT_STREAM_VALUE.
Additional endpoints for retrieving and clearing chat history.
@RestController
@RequestMapping("/chat")
public class ChatController {
private final ChatClient chatClient;
private final ChatMemory chatMemory;
@PostMapping("/call")
public String call(@RequestParam String question, @RequestParam String conversationId) {
List<Message> history = chatMemory.get(conversationId);
chatMemory.add(conversationId, List.of(new UserMessage(question)));
String response = chatClient.prompt()
.messages(history)
.user(question)
.call()
.content();
chatMemory.add(conversationId, List.of(new AssistantMessage(response)));
return response;
}
@PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ChatEventDto> stream(@RequestParam String question, @RequestParam String conversationId) {
List<Message> history = chatMemory.get(conversationId);
chatMemory.add(conversationId, List.of(new UserMessage(question)));
StringBuilder full = new StringBuilder();
return chatClient.prompt()
.messages(history)
.user(question)
.stream()
.content()
.map(content -> {
full.append(content);
return ChatEventDto.builder()
.eventType(ChatEventType.DATA.getValue())
.eventData(content)
.build();
})
.concatWith(Flux.just(ChatEventDto.builder()
.eventType(ChatEventType.STOP.getValue())
.build()))
.doOnComplete(() -> {
if (!full.isEmpty()) {
chatMemory.add(conversationId, List.of(new AssistantMessage(full.toString())));
}
});
}
// /history and /clearHistory endpoints omitted for brevity
}Adding Chat Memory with Redis
Redis‑Stack 7.4.0 is required for the built‑in vector store. Run it via Docker:
docker run --name redis-stack \
-p 6379:6379 \
-p 8001:8001 \
-d redis/redis-stack:7.4.0-v8Add the Redis chat‑memory starter to pom.xml.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-chat-memory-repository-redis</artifactId>
</dependency>Configure Redis connection in application.yaml.
spring:
ai:
chat:
memory:
redis:
host: 192.168.3.101
port: 6379
time-to-live: 24h
key-prefix: spring-chatDefine beans for RedisChatMemoryRepository and ChatMemory (using MessageWindowChatMemory with a max of 100 messages).
@Configuration
public class SpringAIConfig {
@Value("${spring.ai.chat.memory.redis.host}")
private String redisHost;
@Value("${spring.ai.chat.memory.redis.port}")
private int redisPort;
@Bean
public RedisChatMemoryRepository redisChatMemoryRepository() {
RedisClient client = RedisClient.builder()
.hostAndPort(redisHost, redisPort)
.build();
return RedisChatMemoryRepository.builder()
.jedisClient(client)
.build();
}
@Bean
public ChatMemory chatMemory(RedisChatMemoryRepository repository) {
return MessageWindowChatMemory.builder()
.chatMemoryRepository(repository)
.maxMessages(100)
.build();
}
}Testing the Service
Using Postman, the synchronous /chat/call endpoint returns the full response at once, while the streaming /chat/stream endpoint delivers incremental JSON events. The UI built with TDesign’s Chatbot component shows multi‑turn interactions, and the Redis console confirms that conversation history is persisted.
Conclusion
Spring AI 2.0 reduces the effort to embed LLM capabilities in a Spring Boot application to three steps: add the starter, configure model credentials, and inject a ChatClient. By adding the optional Redis‑backed ChatMemory, developers obtain true multi‑turn conversation memory without writing custom persistence code.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
