This article is published in English.
Spring AI vs LangChain4j: Setup, First Endpoint and Design Style
Compare Spring AI and LangChain4j on architecture, Spring Boot starters, configuration and a first REST chat endpoint, and learn which style suits your team.
Feature lists only tell you so much. What you really want to know about a framework is how it feels after a few weeks of building with it, and documentation won't answer that. So picture a team starting a brand-new Spring Boot project and trying both Spring AI and LangChain4j. The comparison below walks through architecture, project setup, configuration, a first AI endpoint, and the day-to-day developer experience. Both libraries solve the same problem, but they go about it very differently.
Two architectural philosophies
The design difference between the two shapes nearly every later decision, so it helps to look at it before writing code.
Spring AI's architecture
Spring AI follows a pattern that any Spring Boot developer will recognize.
Spring Boot Application
│
ChatClient API
│
Spring AI Abstractions
│
OpenAI | Gemini | Ollama | Claude | Azure
│
Large Language Model
The framework sits between your application and the AI provider. Rather than calling OpenAI or Gemini directly, your code talks to Spring AI's abstractions. That pays off in a few ways. Moving from Gemini to OpenAI usually leaves your business code untouched, and only configuration changes. It's the same idea as Spring Data letting you swap databases without rewriting repository logic.
Why this approach feels familiar
For anyone who has built Spring Boot applications for years, the structure is instantly familiar. Dependency injection is at the center, beans are auto-configured, and settings live in application.yml. It doesn't feel like learning an AI framework so much as learning one more Spring starter, and for enterprise teams that's a big advantage.
LangChain4j's architecture
LangChain4j has a different mindset. It doesn't build everything around one central abstraction. It hands you several reusable building blocks instead.
Spring Boot Application
│
AI Service Interface
│
┌──────────┬─────────────┬──────────────┐
│ │ │ │
Chat Model Memory Tools Retriever
│
OpenAI / Gemini / Ollama
It also doesn't hide AI concepts; it exposes them. You'll work with these components directly:
- Chat models and embedding models
- Chat memory
- AI services
- Content retrievers and tool providers
Every one of them has a single clear job, and you assemble them into your own AI pipeline. That can look like extra work at first. Once the application grows, though, the modular design starts to make sense.
Setting up Spring AI
Getting started with Spring AI is quick. Pulling in Spring Data JPA or Spring Security works the same way: you add the matching starter.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-gemini</artifactId>
</dependency>
Then provide your API key in configuration.
spring:
ai:
vertex:
ai:
gemini:
project-id: your-project
location: us-central1
# OR
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
Spring Boot then creates the required beans for you. There are no factory classes, no manual wiring and no builder objects, and everything is ready for dependency injection. To a Spring developer this feels completely natural.
Setting up LangChain4j
LangChain4j ships Spring Boot starters too, and the setup differs only slightly.
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
</dependency>
The configuration looks much the same.
langchain4j:
open-ai:
chat-model:
api-key: ${OPENAI_API_KEY}
model-name: gpt-4o-mini
Again, Spring Boot auto-creates the beans, so for an existing Spring Boot project the experience is almost the same as with Spring AI. LangChain4j adds one more option, though: you can skip the starters entirely and construct everything by hand.
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName("gpt-4o-mini")
.build();
That flexibility is a real plus. In a plain Java application or in Quarkus, nothing changes, because the library isn't tied to Spring.
Building a first AI endpoint
Now for the interesting part. The same REST endpoint gets built with each framework. It accepts a question and returns a generated answer.
The Spring AI version
@RestController
@RequestMapping("/chat")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping
public String chat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
That's surprisingly tidy. The fluent API resembles Spring's WebClient, and each step reads naturally.
prompt()
↓
user()
↓
call()
↓
content()
Anyone who has used Spring's fluent APIs will probably get the idea at a glance.
The LangChain4j version
@RestController
@RequestMapping("/chat")
public class ChatController {
private final ChatLanguageModel model;
public ChatController(ChatLanguageModel model) {
this.model = model;
}
@GetMapping
public String chat(@RequestParam String message) {
return model.generate(message);
}
}
This one is even shorter. Rather than building a prompt through a builder, you talk to the language model directly. There's less ceremony, and the code looks almost like a call to an ordinary Java service.
Which is easier?
Developers often ask this, and the honest answer is that both are excellent. For a basic chat application there's no clear winner. Each needs only a few lines, plugs into Spring Boot, configures its own dependencies, and produces clean, readable code.
The gap isn't in the amount of code. It's in how an application evolves. Spring AI wants everything to flow through a ChatClient, and as a project grows you add Advisors, memory, tool calling, RAG and observability around that client.
LangChain4j goes the other way. It doesn't grow one central client but encourages specialized AI services, so an application ends up looking like this:
CustomerSupportAgent
DocumentAssistant
CodeReviewAgent
EmailGenerator
MeetingSummarizer
Each of those is its own Java interface with a clearly defined job. For larger AI applications this approach is very elegant. If your project already follows traditional Spring service patterns, though, Spring AI will feel more familiar. Neither is objectively better, because they're tuned for different ways of thinking.
What building the same chatbot twice teaches you
A first chatbot in Spring AI feels like writing yet another Spring Boot application. There are few surprises: everything lives where you'd expect, dependency injection behaves as usual, configuration stays in application.yml, and a working AI endpoint can be up within an hour.
Building the same chatbot in LangChain4j produces a different first impression. Instead of integrating an API, you start thinking about designing an intelligent assistant. That's a subtle distinction, but it changes how you organize code. LangChain4j nudges you to separate prompts, tools, memory and retrieval into reusable components from day one, while Spring AI lets you add those capabilities one at a time as the application evolves. Neither philosophy is wrong. The right pick depends on the kind of software you're building and how your team likes to structure a codebase.
Where they really split
At this point the differences are still small. The real divergence shows up once you build production-grade AI features such as structured outputs, tool calling, retrieval-augmented generation and agents. That's where each framework shows its true strengths, and where choosing between them starts to matter much more.