O ecossistema Java está formalizando IA em produção. Este artigo apresenta os blocos concretos de construção para quem quer sair do protótipo e chegar ao contrato estável.
Contexto: o sinal que o ecossistema está dando
Antes de entrar no código, vale nomear o momento. Na sua newsletter de junho de 2026, o professor Elder Moraes — referência no ecossistema Java e criador do Método Java AI Specialist — sintetizou com precisão o que está acontecendo na plataforma:
"O ecossistema Java está colocando estrutura formal em volta do que já roda em produção: padrão de interop, governança de contribuição, default de framework."
— Elder Moraes, Newsletter Java Weekly, jun. 2026 (eldermoraes.ai)
A leitura do professor Moraes é precisa e serve como bússola para este artigo. O A2A Java SDK atingiu GA (1.0.0.Final), o Quarkus 3.37 ativou serialização Jackson livre de reflexão por padrão, e o próprio OpenJDK teve que legislar sobre código gerado por IA — um sinal de que a adoção já acontece em escala. O trabalho do desenvolvedor agora não é mais avaliar se usar IA em Java, mas saber como construir em cima do que já é contrato estável.
Este artigo trata exatamente disso: os três pilares concretos que você pode colocar em produção hoje — LangChain4j como camada de orquestração de LLM, RAG (Retrieval-Augmented Generation) como estratégia de contexto, e MCP (Model Context Protocol) como borda de tool e dados.
LangChain4j: o SDK que já conhece o seu stack
LangChain4j é a port Java do ecossistema LangChain, mas construída com idioma Java de verdade: anotações declarativas, integração nativa com Spring Boot e Quarkus, e suporte a múltiplos provedores de LLM (OpenAI, Anthropic, Ollama, Azure OpenAI, Bedrock, entre outros) trocáveis via configuração, sem alterar a lógica de negócio.
O conceito central é o AI Service: uma interface Java anotada que o framework implementa em tempo de build (ou runtime), abstraindo o ciclo completo de prompt, chamada ao modelo e parse da resposta.
// Declaração da interface — tudo que o dev precisa escrever
@RegisterAiService(retriever = EmbeddingStoreRetriever.class)
public interface DocumentAssistant {
@SystemMessage("Você é um assistente especialista em regulatório financeiro.")
@UserMessage("Com base nos documentos disponíveis, responda: {{question}}")
String answer(@V("question") String question);
}
Com Quarkus, a extensão quarkus-langchain4j injeta o serviço via CDI, resolve o provider de LLM pelo application.properties, e aplica os ganhos de native image automaticamente — incluindo o flip de Jackson reflection-free que o Quarkus 3.37 ativou por padrão, reduzindo cold start e consumo de heap sem nenhuma mudança no código da aplicação.
Configuração mínima com Quarkus + Ollama local
# application.properties
quarkus.langchain4j.ollama.base-url=http://localhost:11434
quarkus.langchain4j.ollama.chat-model.model-id=llama3
quarkus.langchain4j.ollama.embedding-model.model-id=nomic-embed-text
quarkus.langchain4j.ollama.timeout=60s
Para produção, troca-se o bloco ollama por openai ou anthropic sem tocar em nenhuma linha Java. Esse isolamento é o primeiro contrato estável que o arquiteto precisa firmar: a lógica de negócio nunca deve conhecer o provedor de LLM.
RAG: contexto sem alucinação
Modelos de linguagem sabem muito, mas não sabem nada sobre os seus dados. RAG — Retrieval-Augmented Generation — é o padrão que resolve isso: em vez de treinar ou fazer fine-tuning (caro e lento), você recupera os fragmentos mais relevantes dos seus próprios dados no momento da pergunta e os injeta no contexto do prompt.
O pipeline tem três etapas fixas: ingestão (parse e chunking dos documentos), indexação (geração de embeddings e armazenamento em vector store) e recuperação (busca por similaridade no momento da query). LangChain4j cobre todas as três com APIs unificadas.
Pipeline de ingestão
@ApplicationScoped
public class DocumentIngestionService {
@Inject EmbeddingModel embeddingModel;
@Inject EmbeddingStore<TextSegment> embeddingStore;
public void ingest(Path filePath) {
// 1. Carrega o documento (PDF, TXT, HTML...)
Document document = FileSystemDocumentLoader.loadDocument(filePath);
// 2. Divide em chunks com overlap para preservar contexto
DocumentSplitter splitter = DocumentSplitters
.recursive(512, 64, new OpenAiTokenizer());
// 3. Gera embeddings e persiste na vector store
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
.documentSplitter(splitter)
.embeddingModel(embeddingModel)
.embeddingStore(embeddingStore)
.build();
ingestor.ingest(document);
}
}
Recuperação no momento da query
@ApplicationScoped
public class EmbeddingStoreRetriever implements ContentRetriever {
@Inject EmbeddingModel embeddingModel;
@Inject EmbeddingStore<TextSegment> embeddingStore;
@Override
public List<Content> retrieve(Query query) {
Embedding queryEmbedding = embeddingModel
.embed(query.text()).content();
List<EmbeddingMatch<TextSegment>> matches =
embeddingStore.findRelevant(queryEmbedding, 5, 0.75);
return matches.stream()
.map(m -> Content.from(m.embedded()))
.toList();
}
}
Para ambientes enterprise com Oracle ou PostgreSQL (via pgvector), o EmbeddingStore troca de implementação pela configuração — nenhuma linha de recuperação muda. Em produção com base Oracle, o Oracle AI Vector Search (disponível desde o Oracle 23ai) é uma opção que elimina um componente de infraestrutura extra.
"A regra de decisão que eu usaria é separar o que é contrato estável pra construir em cima do que ainda é empolgante-mas-instável."
— Elder Moraes, Newsletter Java Weekly, jun. 2026 (eldermoraes.ai)
Aplicando a regra do professor Moraes ao RAG: o padrão de pipeline (ingestão, embedding, busca por similaridade, augmented prompt) é contrato estável. O que ainda varia é a escolha de vector store e o tamanho ótimo de chunk para o seu domínio. Mexa no segundo, confie no primeiro.
MCP: a borda de ferramenta que o seu agente precisa
Model Context Protocol (MCP) é o padrão aberto, governado pela Anthropic e adotado pela indústria, para expor ferramentas e fontes de dados a modelos de linguagem de forma interoperável. Se o RAG resolve o problema de conhecimento (o que o modelo sabe), o MCP resolve o problema de ação (o que o modelo pode fazer).
A distinção entre o A2A (Agent2Agent, para comunicação agente-a-agente) e o MCP (para a borda de tool e dados) é fundamental para uma arquitetura limpa. Misturar os dois papéis em um único componente é o caminho mais curto para um sistema impossível de testar.
Servidor MCP em Quarkus
A extensão quarkus-mcp-server expõe beans CDI como ferramentas MCP com uma única anotação:
@ApplicationScoped
public class ContaCorrenteTools {
@Inject ContaCorrenteRepository repository;
@Tool("Consulta o saldo atual de uma conta corrente pelo número da conta")
public SaldoResponse consultarSaldo(
@P("Número da conta no formato XXXXXXX-D") String numeroConta) {
return repository.findSaldo(numeroConta)
.map(SaldoResponse::of)
.orElseThrow(() -> new ContaNaoEncontradaException(numeroConta));
}
@Tool("Lista os últimos lançamentos de uma conta em um período")
public List<LancamentoResponse> listarLancamentos(
@P("Número da conta") String numeroConta,
@P("Data inicial no formato yyyy-MM-dd") String dataInicio,
@P("Data final no formato yyyy-MM-dd") String dataFim) {
return repository.findLancamentos(numeroConta,
LocalDate.parse(dataInicio), LocalDate.parse(dataFim));
}
}
O Quarkus registra automaticamente essas ferramentas no endpoint MCP da aplicação. Um agente externo — seja um assistente Claude, seja um orquestrador LangChain4j do próprio sistema — descobre e chama as ferramentas via protocolo padrão sem conhecer a implementação Java.
Consumindo ferramentas MCP a partir de um AI Service
@RegisterAiService(tools = McpToolProvider.class)
public interface AssistenteFinanceiro {
@SystemMessage("""
Você é um assistente financeiro cooperativista.
Use as ferramentas disponíveis para consultar dados reais antes de responder.
Nunca invente números. Se não tiver dados suficientes, diga claramente.
""")
String conversar(@MemoryId String sessionId,
@UserMessage String mensagem);
}
O ciclo completo fica assim: o usuário envia uma mensagem, o LLM decide quais ferramentas chamar, o Quarkus executa as chamadas MCP contra os seus próprios endpoints Java, os resultados retornam ao LLM como contexto, e a resposta final é gerada com dados reais. Tudo rastreável, tudo testável.
Juntando os três: arquitetura de referência
O fluxo completo de uma pergunta do usuário até a resposta com dados reais e contexto documental:
Usuário
|
v
[AssistenteFinanceiro — AI Service]
|
|-- (1) Recuperação RAG --> EmbeddingStoreRetriever
| |
| Vector Store
| |
| Fragmentos relevantes <--|
|
|-- (2) Tool calls via MCP --> ContaCorrenteTools
| |
| Repository / Oracle DB
| |
| Dados transacionais <--|
|
v
[LLM: Prompt = contexto RAG + dados MCP + histórico de sessão]
|
v
Resposta fundamentada
Cada camada tem uma responsabilidade única. O AI Service orquestra. O RAG fornece conhecimento documental. O MCP fornece dados transacionais em tempo real. O LLM sintetiza. Nenhuma camada precisa conhecer as outras diretamente — apenas o contrato de interface.
A questão que ninguém está fazendo: governança de código gerado por IA
Há um aspecto que vai além da arquitetura técnica e que o professor Moraes nomeia com precisão na sua newsletter: a oportunidade real não está em adotar o framework mais novo, mas em ser o desenvolvedor que sabe governar o uso de IA no time.
A decisão do OpenJDK de barrar contribuições geradas por LLM — mantendo o uso privado para entender, debugar e revisar — e a decisão oposta da GraalVM ilustram que não existe uma resposta única. O que existe é a necessidade de uma política deliberada. Para um time que usa assistentes de IA no dia a dia, as perguntas práticas são:
- Quais artefatos gerados por IA exigem revisão humana obrigatória antes do merge?
- Como o time documenta a origem de um trecho crítico de lógica de negócio?
- O pipeline de CI valida cobertura de testes mesmo quando o código é gerado automaticamente?
- Existe um critério explícito para o que é "plausível mas errado" — o risco que o OpenJDK identificou como custo real de review?
Essas perguntas têm respostas técnicas (regras de linter, gates no pipeline, cobertura mínima), mas a decisão de fazer as perguntas é liderança de engenharia.
O que construir agora e o que esperar
Voltando à divisão que o professor Moraes propõe — contrato estável versus empolgante-mas-instável:
Construa agora:
- AI Service com LangChain4j declarativo
- Pipeline RAG com vector store já disponível na sua infraestrutura (Oracle ou Postgres)
- Exposição de ferramentas via MCP a partir de beans CDI existentes
- Política interna de governança de código gerado por IA
Acompanhe, não deploya ainda:
- A2A SDK (GA, mas o ecossistema de frameworks ao redor ainda está em movimento)
- Project Valhalla value classes (preview no JDK 28, provavelmente ainda em preview no próximo LTS)
- TLS pós-quântico do JDK 27 (meça latência de handshake e compatibilidade com load balancers antes de assumir que vem de graça)
O ecossistema Java tem histórico de levar tempo para padronizar e, quando padroniza, padronizar de forma que dura décadas. O desenvolvedor que entender os contratos estáveis hoje vai construir sobre fundação sólida enquanto o restante ainda debate qual framework adotar.
Referências
[1] MORAES, Elder. A2A Java SDK 1.0.0.Final: o primeiro GA. Newsletter Java Weekly, jun. 2026. Disponível em: https://quarkus.io/blog/a2a-java-sdk-1-0-0-final-released/ (citado via newsletter eldermoraes.ai).
[2] MORAES, Elder. Quarkus 3.37 liga o Jackson reflection-free por padrão. Newsletter Java Weekly, jun. 2026. Disponível em: https://github.com/quarkusio/quarkus/releases/tag/3.37.0.CR1 (citado via newsletter eldermoraes.ai).
[3] MORAES, Elder. OpenJDK proíbe contribuição gerada por IA; a GraalVM, da mesma Oracle, permite. Newsletter Java Weekly, jun. 2026. Disponível em: https://www.infoq.com/news/2026/06/oracle-genai-policies/ (citado via newsletter eldermoraes.ai).
[4] MORAES, Elder. Método Java AI Specialist. Disponível em: https://eldermoraes.ai. Acesso em: jun. 2026.
[5] LangChain4j. Documentation. Disponível em: https://docs.langchain4j.dev.
[6] Quarkus. LangChain4j Extension Guide. Disponível em: https://quarkus.io/guides/langchain4j.
[7] Anthropic. Model Context Protocol Specification. Disponível em: https://modelcontextprotocol.io.