Add langchain4j-interop: Spring AI 2.0 and LangChain4j 1.22 side by side

Same order assistant in both frameworks against a local fake OpenAI
server: starter bean collision, wire differences, tool failure and loop
bounds, observability meters, MCP-first tools, and a compile check of
the 2025 article's snippets and Maven coordinates.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01G8ikz8xdWuTP5yun8DZ1hk
This commit is contained in:
Claude
2026-10-11 10:09:45 +00:00
parent d51ef56468
commit e79b75a105
35 changed files with 1330 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
# Compiles each API line of the original (2025-era) article, one file each, against today's Spring AI 2.0.1 and
# LangChain4j 1.22.0 jars, and records what the compiler says. Also looks up the original Maven coordinates.
set -uo pipefail
cd "$(dirname "$0")/.."
OUT=output/06-old-code-vs-current.txt
mvn -q -B dependency:build-classpath -Dmdep.outputFile=target/cp.txt -Dmdep.includeScope=test >/dev/null 2>&1
CP="$(cat target/cp.txt)"
mkdir -p target/old
{
echo "# The original article's code, compiled against Spring AI 2.0.1 and LangChain4j 1.22.0 (one file per API line)"
echo
for f in src/broken/Old*.java; do
n=$(basename "$f" .java)
rm -rf target/old/$n; mkdir -p target/old/$n
if err=$(javac -proc:none --release 25 -cp "$CP" -d target/old/$n "$f" 2>&1 | grep -v '^Picked up' | grep -v '^Note:'); then :; fi
if [ -z "$err" ]; then
echo "$n: compiles"
else
echo "$n: DOES NOT COMPILE"
echo "$err" | grep -E "error:|symbol:|location:" | head -6 | sed 's#^src/broken/##; s/^/ /'
fi
done
echo
echo "# The original article's Maven coordinates, looked up on Maven Central"
echo
meta() { # groupPath artifact
for try in 1 2 3 4 5 6; do
code=$(curl -s -o target/meta.xml -w '%{http_code}' "https://repo1.maven.org/maven2/$1/$2/maven-metadata.xml" || echo 000)
case "$code" in 200|404) break;; esac
sleep $((try * 8))
done
if [ "$code" = "404" ]; then echo "$1/$2: no such artifact"; return; fi
if [ "$code" != "200" ]; then echo "$1/$2: lookup failed (HTTP $code)"; return; fi
all=$(tr '\n' ' ' < target/meta.xml | grep -o '<version>[^<]*</version>' | sed 's/<[^>]*>//g')
ga=$(echo "$all" | grep -v -E 'M[0-9]|RC|beta|alpha|SNAPSHOT' | tail -1)
last=$(echo "$all" | tail -1)
echo "$1/$2: latest release ${ga:-none}, latest of any kind $last"
}
meta org/springframework/ai spring-ai-openai-spring-boot-starter
meta org/springframework/ai spring-ai-pgvector-store-spring-boot-starter
meta org/springframework/ai spring-ai-starter-model-openai
meta org/springframework/ai spring-ai-starter-vector-store-pgvector
meta dev/langchain4j langchain4j-spring-boot-starter
meta dev/langchain4j langchain4j-open-ai
meta dev/langchain4j langchain4j-spring-boot4-starter
echo
echo "# Class names the original article used, searched in the jars this build resolves (mvn dependency:build-classpath)"
echo
mvn -q -B dependency:build-classpath -Dmdep.outputFile=target/cp.txt >/dev/null 2>&1
for name in TokenBudgetAdvisor RequestResponseAdvisor CallAroundAdvisor CallAdvisor ToolCallingAdvisor AdvisedRequest ChatClientRequest EmbeddingClient EmbeddingModel; do
hits=0
for j in $(tr ':' ' ' < target/cp.txt); do
listing=$(unzip -l "$j" 2>/dev/null || true)
if grep -q "/$name\.class" <<< "$listing"; then hits=$((hits+1)); fi
done
if [ "$hits" -gt 0 ]; then echo "$name: found"; else echo "$name: not found in any jar"; fi
done
} > "$OUT"
cat "$OUT"