diff --git a/core-java-modules/core-java-string-algorithms-5/src/main/java/com/baeldung/uniqueint/StringToUniqueInt.java b/core-java-modules/core-java-string-algorithms-5/src/main/java/com/baeldung/uniqueint/StringToUniqueInt.java
index 5128714be205..2eb104f05018 100644
--- a/core-java-modules/core-java-string-algorithms-5/src/main/java/com/baeldung/uniqueint/StringToUniqueInt.java
+++ b/core-java-modules/core-java-string-algorithms-5/src/main/java/com/baeldung/uniqueint/StringToUniqueInt.java
@@ -38,12 +38,12 @@ public static int toIntByMD5(String value) {
}
public static int toIntByLookup(String value) {
- var found = lookupMap.get(value);
+ Integer found = lookupMap.get(value);
if (found != null) {
return found;
}
- var intValue = counter.incrementAndGet();
+ Integer intValue = counter.incrementAndGet();
lookupMap.put(value, intValue);
return intValue;
}
diff --git a/pom.xml b/pom.xml
index d3db76e746de..cc376aacd99d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -764,6 +764,7 @@
spring-ai
spring-ai-2
spring-ai-3
+ spring-ai-4
spring-ai-modules
spring-aop
spring-aop-2
@@ -1196,6 +1197,7 @@
spring-ai
spring-ai-2
spring-ai-3
+ spring-ai-4
spring-ai-modules
spring-aop
spring-aop-2
diff --git a/spring-ai-4/pom.xml b/spring-ai-4/pom.xml
new file mode 100644
index 000000000000..ac2466af39f8
--- /dev/null
+++ b/spring-ai-4/pom.xml
@@ -0,0 +1,119 @@
+
+
+ 4.0.0
+ spring-ai-4
+ 0.0.1
+ jar
+ spring-ai-4
+
+
+ com.baeldung
+ parent-boot-3
+ 0.0.1-SNAPSHOT
+ ../parent-boot-3
+
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+ true
+
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+ false
+
+
+
+
+
+
+
+ org.springframework.ai
+ spring-ai-bom
+ ${spring-ai.version}
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.ai
+ spring-ai-starter-model-openai
+
+
+ org.springframework.ai
+ spring-ai-model-chat-memory-repository-jdbc
+
+
+ org.hsqldb
+ hsqldb
+ runtime
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ chat-memory
+
+ true
+
+
+ com.baeldung.springai.memory.Application
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ ${spring.boot.mainclass}
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 21
+
+
+
+
+
+
+ 5.9.0
+ 3.5.0
+ 1.0.0
+
+
+
diff --git a/spring-ai-4/src/main/java/com/baeldung/springai/memory/Application.java b/spring-ai-4/src/main/java/com/baeldung/springai/memory/Application.java
new file mode 100644
index 000000000000..5cdaa360c6bc
--- /dev/null
+++ b/spring-ai-4/src/main/java/com/baeldung/springai/memory/Application.java
@@ -0,0 +1,15 @@
+package com.baeldung.springai.memory;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication app = new SpringApplication(Application.class);
+ app.setAdditionalProfiles("memory");
+ app.run(args);
+ }
+
+}
diff --git a/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatConfig.java b/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatConfig.java
new file mode 100644
index 000000000000..a44f8f7d0739
--- /dev/null
+++ b/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatConfig.java
@@ -0,0 +1,21 @@
+package com.baeldung.springai.memory;
+
+import org.springframework.ai.chat.memory.ChatMemoryRepository;
+import org.springframework.ai.chat.memory.repository.jdbc.HsqldbChatMemoryRepositoryDialect;
+import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+@Configuration
+public class ChatConfig {
+
+ @Bean
+ public ChatMemoryRepository getChatMemoryRepository(JdbcTemplate jdbcTemplate) {
+ return JdbcChatMemoryRepository.builder()
+ .jdbcTemplate(jdbcTemplate)
+ .dialect(new HsqldbChatMemoryRepositoryDialect())
+ .build();
+ }
+
+}
diff --git a/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatController.java b/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatController.java
new file mode 100644
index 000000000000..f860eea77ca0
--- /dev/null
+++ b/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatController.java
@@ -0,0 +1,25 @@
+package com.baeldung.springai.memory;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+@RestController
+public class ChatController {
+
+ private final ChatService chatService;
+
+ public ChatController(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ @PostMapping("/chat")
+ public ResponseEntity chat(@RequestBody @Valid ChatRequest request) {
+ String response = chatService.chat(request.getPrompt());
+ return ResponseEntity.ok(response);
+ }
+
+}
diff --git a/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatRequest.java b/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatRequest.java
new file mode 100644
index 000000000000..cedefe07fa35
--- /dev/null
+++ b/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatRequest.java
@@ -0,0 +1,18 @@
+package com.baeldung.springai.memory;
+
+import javax.validation.constraints.NotNull;
+
+public class ChatRequest {
+
+ @NotNull
+ private String prompt;
+
+ public String getPrompt() {
+ return prompt;
+ }
+
+ public void setPrompt(String prompt) {
+ this.prompt = prompt;
+ }
+
+}
diff --git a/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatService.java b/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatService.java
new file mode 100644
index 000000000000..64fc63acca79
--- /dev/null
+++ b/spring-ai-4/src/main/java/com/baeldung/springai/memory/ChatService.java
@@ -0,0 +1,38 @@
+package com.baeldung.springai.memory;
+
+import org.springframework.ai.chat.client.ChatClient;
+import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
+import org.springframework.ai.chat.memory.ChatMemory;
+import org.springframework.ai.chat.model.ChatModel;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.annotation.SessionScope;
+
+import java.util.UUID;
+
+@Component
+@SessionScope
+public class ChatService {
+
+ private final ChatClient chatClient;
+ private final String conversationId;
+
+ public ChatService(ChatModel chatModel, ChatMemory chatMemory) {
+ this.chatClient = ChatClient.builder(chatModel)
+ .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
+ .build();
+ this.conversationId = UUID.randomUUID().toString();
+ }
+
+ public String getConversationId() {
+ return conversationId;
+ }
+
+ public String chat(String prompt) {
+ return chatClient.prompt()
+ .user(userMessage -> userMessage.text(prompt))
+ .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
+ .call()
+ .content();
+ }
+
+}
diff --git a/spring-ai-4/src/main/resources/application-memory.yml b/spring-ai-4/src/main/resources/application-memory.yml
new file mode 100644
index 000000000000..a0531b4eab58
--- /dev/null
+++ b/spring-ai-4/src/main/resources/application-memory.yml
@@ -0,0 +1,15 @@
+spring:
+ ai:
+ openai:
+ api-key: ""
+
+ datasource:
+ url: jdbc:hsqldb:mem:chatdb
+ driver-class-name: org.hsqldb.jdbc.JDBCDriver
+ username: sa
+ password:
+
+ sql:
+ init:
+ mode: always
+ schema-locations: classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-hsqldb.sql
diff --git a/spring-ai-4/src/main/resources/logback.xml b/spring-ai-4/src/main/resources/logback.xml
new file mode 100644
index 000000000000..449efbdaebb0
--- /dev/null
+++ b/spring-ai-4/src/main/resources/logback.xml
@@ -0,0 +1,15 @@
+
+
+
+ [%d{yyyy-MM-dd HH:mm:ss}] [%p] [%c{1}] - %m%n
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-ai-4/src/test/java/com/baeldung/springai/memory/ChatServiceLiveTest.java b/spring-ai-4/src/test/java/com/baeldung/springai/memory/ChatServiceLiveTest.java
new file mode 100644
index 000000000000..c96024846a92
--- /dev/null
+++ b/spring-ai-4/src/test/java/com/baeldung/springai/memory/ChatServiceLiveTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.springai.memory;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.ai.chat.memory.ChatMemory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@SpringBootTest
+@ActiveProfiles("memory")
+class ChatServiceLiveTest {
+
+ private static final String PROMPT_1ST = "Tell me a joke";
+ private static final String PROMPT_2ND = "Tell me another one";
+
+ @Autowired
+ private ChatMemory chatMemory;
+
+ @Autowired
+ private ChatService chatService;
+
+ @Test
+ void whenChatServiceIsCalledTwice_thenChatMemoryHasCorrectNumberOfEntries() {
+ String conversationId = chatService.getConversationId();
+
+ // 1st request
+ String response1 = chatService.chat(PROMPT_1ST);
+ assertThat(response1).isNotEmpty();
+ assertThat(chatMemory.get(conversationId)).hasSize(2);
+
+ // 2nd request
+ String response2 = chatService.chat(PROMPT_2ND);
+ assertThat(response2).isNotEmpty();
+ assertThat(chatMemory.get(conversationId)).hasSize(4);
+ }
+
+}
\ No newline at end of file