<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app-kqfaxawkj" -->

---
title: Spring AI 2.0 in Practice: Adding LLM Features to a Java...
description: A hands-on walkthrough builds a complete AI chat assistant inside a Java Spring Boot app using Spring AI 2.0, Vaadin for the UI, and no JavaScript. It covers...
canonical: https://daily.dev/posts/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app-kqfaxawkj
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Spring AI 2.0 in Practice: Adding LLM Features to a Java Web App | daily.dev
og:description: A hands-on walkthrough builds a complete AI chat assistant inside a Java Spring Boot app using Spring AI 2.0, Vaadin for the UI, and no JavaScript. It covers...
og:url: https://daily.dev/posts/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app-kqfaxawkj
og:image: https://api.daily.dev/og/posts/KQfaXAWkj.png
og:image:alt: Spring AI 2.0 in Practice: Adding LLM Features to a Java Web App
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Spring AI 2.0 in Practice: Adding LLM Features to a Java Web App

**[Vaadin](https://daily.dev/sources/vaadin)** · 18 min read · 1 upvotes · 0 comments

## Summary

A hands-on walkthrough builds a complete AI chat assistant inside a Java Spring Boot app using Spring AI 2.0, Vaadin for the UI, and no JavaScript. It covers streaming token-by-token responses, wiring up RAG with a vector store, tracking token costs via Micrometer, and handling failures gracefully. It also compares Spring AI against LangChain4j, explaining when to reach for each, and calls out that Spring AI 2.0 removed the QuestionAnswerAdvisor in favor of RetrievalAugmentationAdvisor. Several production gotchas are highlighted: Claude models reject sampling parameters like temperature, Anthropic lacks an embedding API, and setting an unmeasured similarityThreshold can silently break RAG retrieval with no errors.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://blog.vaadin.com/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app>

## Questions this post answers

### Why does my Spring AI RAG application say it doesn't know the answer even though the documents were ingested?

The most common cause is a similarityThreshold on the document retriever set too high for the embedding model in use, causing retrieval to return zero matches with no error or warning. The app looks healthy and the model just answers that it doesn't know. The fix is to remove the threshold, confirm retrieval returns documents using topK alone, then re-add a threshold only as a measured value specific to that embedding model.

_Anyone debugging a silently broken RAG pipeline can compare notes on similarity thresholds via daily.dev._

### What replaced QuestionAnswerAdvisor in Spring AI 2.0 for RAG?

Spring AI 2.0 removed QuestionAnswerAdvisor and replaced it with RetrievalAugmentationAdvisor, found in the spring-ai-rag module, composed with a DocumentRetriever such as VectorStoreDocumentRetriever. It is more verbose than the old advisor but makes retrieval parameters explicit and supports query transformers and post-processors through the same builder.

_daily.dev helps Java developers stay ahead of breaking API changes like this one in Spring AI._

### Why does setting a temperature parameter break my Spring AI chat app using Claude models?

Current Claude models reject sampling parameters like temperature, top-p, and top-k outright, returning a 400 invalid_request_error at runtime even though the app compiles and starts fine. Spring AI accepts the configuration without complaint, so the failure only surfaces on the first real API call. Steer model behavior through the system prompt instead of temperature settings.

_Java developers wiring Claude into Spring AI can track gotchas like this one through daily.dev._

## Similar posts on daily.dev

- [Spring AI tutorial: Get started with Spring AI](https://daily.dev/posts/spring-ai-tutorial-get-started-with-spring-ai-phjfbwkwg) · InfoWorld · 0 upvotes · 0 comments
- [RAG with Spring AI](https://daily.dev/posts/rag-with-spring-ai-aalrsnemm) · Javarevisited · 6 upvotes · 0 comments
- [Spring AI Series](https://daily.dev/posts/spring-ai-series-j7w3rmryb) · Baeldung · 4 upvotes · 0 comments

---

Tags: [#java](https://daily.dev/tags/java), [#rag](https://daily.dev/tags/rag), [#spring-ai](https://daily.dev/tags/spring-ai), [#vaadin](https://daily.dev/tags/vaadin), [#langchain4j](https://daily.dev/tags/langchain4j)

[View this post on daily.dev](https://daily.dev/posts/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app-kqfaxawkj)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Spring AI 2.0 in Practice: Adding LLM Features to a Java Web App","url":"https://daily.dev/posts/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app-kqfaxawkj","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app-kqfaxawkj"},"datePublished":"2026-08-14T14:25:55.866Z","dateModified":"2026-09-14T07:54:28.136Z","description":"A hands-on walkthrough builds a complete AI chat assistant inside a Java Spring Boot app using Spring AI 2.0, Vaadin for the UI, and no JavaScript. It covers...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/f1266cfa0a2d5668bc9fd3eb5f85c1e9?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/f1266cfa0a2d5668bc9fd3eb5f85c1e9?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Vaadin","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Vaadin","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/052f2fad97c542a19c754e60d6264e45","url":"https://daily.dev/sources/vaadin"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app-kqfaxawkj","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"java,rag,spring-ai,vaadin,langchain4j","timeRequired":"PT18M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Vaadin","item":"https://daily.dev/sources/vaadin"},{"@type":"ListItem","position":3,"name":"Spring AI 2.0 in Practice: Adding LLM Features to a Java Web App"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/spring-ai-2-0-in-practice-adding-llm-features-to-a-java-web-app-kqfaxawkj#faq","mainEntity":[{"@type":"Question","name":"Why does my Spring AI RAG application say it doesn't know the answer even though the documents were ingested?","acceptedAnswer":{"@type":"Answer","text":"The most common cause is a similarityThreshold on the document retriever set too high for the embedding model in use, causing retrieval to return zero matches with no error or warning. The app looks healthy and the model just answers that it doesn't know. The fix is to remove the threshold, confirm retrieval returns documents using topK alone, then re-add a threshold only as a measured value specific to that embedding model. Anyone debugging a silently broken RAG pipeline can compare notes on similarity thresholds via daily.dev."}},{"@type":"Question","name":"What replaced QuestionAnswerAdvisor in Spring AI 2.0 for RAG?","acceptedAnswer":{"@type":"Answer","text":"Spring AI 2.0 removed QuestionAnswerAdvisor and replaced it with RetrievalAugmentationAdvisor, found in the spring-ai-rag module, composed with a DocumentRetriever such as VectorStoreDocumentRetriever. It is more verbose than the old advisor but makes retrieval parameters explicit and supports query transformers and post-processors through the same builder. daily.dev helps Java developers stay ahead of breaking API changes like this one in Spring AI."}},{"@type":"Question","name":"Why does setting a temperature parameter break my Spring AI chat app using Claude models?","acceptedAnswer":{"@type":"Answer","text":"Current Claude models reject sampling parameters like temperature, top-p, and top-k outright, returning a 400 invalid_request_error at runtime even though the app compiles and starts fine. Spring AI accepts the configuration without complaint, so the failure only surfaces on the first real API call. Steer model behavior through the system prompt instead of temperature settings. Java developers wiring Claude into Spring AI can track gotchas like this one through daily.dev."}}]}
```

