{"slug": "context-aware-spring-ai-chat-microservice", "title": "Context aware Spring AI chat microservice", "summary": "A developer demonstrated how to build a context-aware Spring Boot chat microservice that connects to Google's Gemini API using Spring AI's ChatMemory Advisor to maintain conversation history. The implementation persists chat sessions across application restarts by backing the memory with a file-based H2 database via JdbcChatMemoryRepository, keyed to unique user sessions.", "body_md": "By default, Large Language Models (LLMs) are **completely stateless**. Every API call you make to Google Gemini is treated like a first-time introduction. If a user says \"*My name is Alex*\" in request one, and \"*What is my name?*\" in request two, Gemini will not know the answer.\n\nTo build a true chatbot experience, your microservice needs to remember the conversation history.\n\nIn this post, we will build a **Spring Boot microservice** that connects to the **Gemini API**, uses **Spring AI's ChatMemory Advisor** to maintain context, and backs up that history using a persistent **H2 database** mapped to unique user sessions.\n\nThe Architecture\n\nAdd the required dependencies to your pom.xml. This includes the Spring AI starter for Gemini, the chat memory module, and the H2 database driver.\n\n```\n<dependency>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-h2console</artifactId>\n</dependency>\n\n<dependency>\n    <groupId>org.springframework.ai</groupId>\n    <artifactId>spring-ai-starter-model-chat-memory</artifactId>\n</dependency>\n\n<dependency>\n    <groupId>org.springframework.ai</groupId>\n    <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>\n</dependency>\n\n<dependency>\n    <groupId>org.springframework.ai</groupId>\n    <artifactId>spring-ai-starter-model-google-genai</artifactId>\n</dependency>\n```\n\n**Configure Properties**: Update the *application.properties* with chat model and get your API key from [Google AI Studio](https://aistudio.google.com/apikey)\n\n```\nspring.ai.model.chat=google-genai\nspring.ai.google.genai.api-key=API-KEY-GOES-HERE\nspring.ai.google.genai.chat.model=gemini-3.5-flash\n```\n\nInstead of losing chat history on application restarts (which happens with default in-memory arrays), we configure a persistent ChatMemory bean backed by **H2** using the JdbcChatMemoryRepository.\n\n``` python\nimport org.springframework.ai.chat.memory.ChatMemory;\nimport org.springframework.ai.chat.memory.MessageWindowChatMemory;\nimport org.springframework.ai.chat.memory.repository.jdbc.H2ChatMemoryRepositoryDialect;\nimport org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.jdbc.core.JdbcTemplate;\n\n@Configuration\npublic class ChatConfig {\n\n    @Bean\n    public JdbcChatMemoryRepository chatMemoryRepository(JdbcTemplate jdbcTemplate) {\n        // Enforces H2 syntax quirks for database execution\n        return JdbcChatMemoryRepository.builder().jdbcTemplate(jdbcTemplate)\n                .dialect(new H2ChatMemoryRepositoryDialect())\n                .build();\n    }\n\n    @Bean\n    public ChatMemory chatMemory(JdbcChatMemoryRepository repository) {\n        return MessageWindowChatMemory.builder()\n                .chatMemoryRepository(repository).build();\n    }\n\n}\n```\n\n**Configure properties**: include the below in *application.properties* to maintain the session across application restarts and to enable h2-console\n\n```\n# H2 Database configuration (File-based storage to persist across restarts)\nspring.datasource.url=jdbc:h2:file:~/data/demochat;DB_CLOSE_ON_EXIT=FALSE\nspring.datasource.driverClassName=org.h2.Driver\nspring.datasource.username=sa\nspring.datasource.password=password\n\n# Enable H2 Console to view your tables manually at http://localhost:8080/h2-console\nspring.h2.console.enabled=true\nspring.h2.console.path=/h2-console\n\n# Spring AI - Auto-initialize the schema for H2\nspring.ai.chat.memory.repository.jdbc.initialize-schema=always\n```\n\nWe build the ChatClient and attach the MessageChatMemoryAdvisor. This advisor acts as an interceptor: it fetches past messages from H2 before sending the prompt to Gemini, and saves Gemini's response right after.\n\n``` python\nimport org.springframework.ai.chat.client.ChatClient;\nimport org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;\nimport org.springframework.ai.chat.memory.ChatMemory;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class ChatService {\n    private final ChatClient chatClient;\n\n    public ChatService(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory){\n        this.chatClient = chatClientBuilder.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())\n                .build();\n    }\n\n    public String getResponse(String sessionId, String queryString){\n        return this.chatClient.prompt(queryString)\n                .advisors(x -> x.param(ChatMemory.CONVERSATION_ID, sessionId))\n                .call().content();\n    }\n}\n```\n\nFinally, we expose a POST endpoint. We use @RequestHeader(\"x-session-id\") to extract the unique tracking key provided by the client application.\n\n``` python\nimport ai.chat_bot.gemini.demo.service.ChatService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\n@RestController\n@RequestMapping(\"/api\")\npublic class ChatController {\n    @Autowired\n    private ChatService chatService;\n\n    @PostMapping(\"/ai/prompt\")\n    public String chat(@RequestHeader(\"x-session-id\") String sessionId, @RequestBody String query){\n        return chatService.getResponse(sessionId, query);\n    }\n}\n```\n\nYou can test the context awareness using curl or Postman.\n\n**Request establishing a context**:\n\n```\ncurl --location --request POST 'http://localhost:8080/api/ai/prompt' \\\n--header 'x-session-id: 8757788243' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n    \"query\": \"I love mangoes\"\n}'\n```\n\n*Response: Mangoes are absolutely elite! There is a very good reason they are called the **\"King of Fruits.\"** There is nothing quite like a perfectly ripe, juicy, sweet mango.*\n\n**Request to verify history recall**\n\n```\ncurl --location --request POST 'http://localhost:8080/api/ai/prompt' \\\n--header 'x-session-id: 8757788243' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n    \"query\": \"what do you think is my favorite fruit\"\n}'\n```\n\n*Response: I’m going to go out on a limb here and make a wild guess... **mangoes**? 🥭 😉 \nCall it a hunch, but you seemed pretty enthusiastic about them a moment ago!*\n\nIf you send the second request with a different session-id value, Gemini will correctly respond that it doesn't know and can give a generic response proving that **multi-user session isolation is fully working**.\n\nBy combining **Spring AI's Advisor API** with an **H2 JDBC store**, you can turn a stateless LLM endpoint into a fully stateful, context-aware chatbot microservice with minimal boilerplate code.\n\nYou can view the source code directly in my [GitHub Repository](https://github.com/deepakmarneni/context-aware-chat-ai)", "url": "https://wpnews.pro/news/context-aware-spring-ai-chat-microservice", "canonical_source": "https://dev.to/marinenimd/context-aware-spring-ai-chat-microservice-ake", "published_at": "2026-09-13 19:56:40+00:00", "updated_at": "2026-09-13 20:20:35.576439+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "large-language-models", "ai-products"], "entities": ["Spring AI", "Spring Boot", "Google Gemini", "H2 Database", "Google AI Studio", "ChatMemory Advisor", "JdbcChatMemoryRepository"], "alternates": {"html": "https://wpnews.pro/news/context-aware-spring-ai-chat-microservice", "markdown": "https://wpnews.pro/news/context-aware-spring-ai-chat-microservice.md", "text": "https://wpnews.pro/news/context-aware-spring-ai-chat-microservice.txt", "jsonld": "https://wpnews.pro/news/context-aware-spring-ai-chat-microservice.jsonld"}}