diff --git a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryAutoConfiguration.java b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryAutoConfiguration.java index bc811c3ded6..e9d1b2aa10c 100644 --- a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryAutoConfiguration.java +++ b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryAutoConfiguration.java @@ -26,20 +26,25 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration; +import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; +import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Import; import org.springframework.jdbc.core.JdbcTemplate; /** * @author Jonathan Leijendekker + * @author Eddú Meléndez * @since 1.0.0 */ @AutoConfiguration(after = JdbcTemplateAutoConfiguration.class) @ConditionalOnClass({ JdbcChatMemory.class, DataSource.class, JdbcTemplate.class }) @EnableConfigurationProperties(JdbcChatMemoryProperties.class) +@Import(DatabaseInitializationDependencyConfigurer.class) public class JdbcChatMemoryAutoConfiguration { private static final Logger logger = LoggerFactory.getLogger(JdbcChatMemoryAutoConfiguration.class); @@ -54,12 +59,20 @@ public JdbcChatMemory chatMemory(JdbcTemplate jdbcTemplate) { @Bean @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.ai.chat.memory.jdbc.initialize-schema", havingValue = "true", - matchIfMissing = true) - public DataSourceScriptDatabaseInitializer jdbcChatMemoryScriptDatabaseInitializer(DataSource dataSource) { + @Conditional(OnJdbcChatMemoryDatasourceInitializationCondition.class) + public DataSourceScriptDatabaseInitializer jdbcChatMemoryScriptDatabaseInitializer(DataSource dataSource, + JdbcChatMemoryProperties properties) { logger.debug("Initializing JdbcChatMemory schema"); - return new JdbcChatMemoryDataSourceScriptDatabaseInitializer(dataSource); + return new JdbcChatMemoryDataSourceScriptDatabaseInitializer(dataSource, properties); + } + + static class OnJdbcChatMemoryDatasourceInitializationCondition extends OnDatabaseInitializationCondition { + + OnJdbcChatMemoryDatasourceInitializationCondition() { + super("Jdbc Chat Memory", "spring.ai.chat.memory.jdbc.initialize-schema"); + } + } } diff --git a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryDataSourceScriptDatabaseInitializer.java b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryDataSourceScriptDatabaseInitializer.java index 2f1927048df..5202a9da41c 100644 --- a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryDataSourceScriptDatabaseInitializer.java +++ b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryDataSourceScriptDatabaseInitializer.java @@ -6,21 +6,21 @@ import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; import org.springframework.boot.jdbc.init.PlatformPlaceholderDatabaseDriverResolver; -import org.springframework.boot.sql.init.DatabaseInitializationMode; import org.springframework.boot.sql.init.DatabaseInitializationSettings; class JdbcChatMemoryDataSourceScriptDatabaseInitializer extends DataSourceScriptDatabaseInitializer { private static final String SCHEMA_LOCATION = "classpath:org/springframework/ai/chat/memory/jdbc/schema-@@platform@@.sql"; - public JdbcChatMemoryDataSourceScriptDatabaseInitializer(DataSource dataSource) { - super(dataSource, getSettings(dataSource)); + public JdbcChatMemoryDataSourceScriptDatabaseInitializer(DataSource dataSource, + JdbcChatMemoryProperties properties) { + super(dataSource, getSettings(dataSource, properties)); } - static DatabaseInitializationSettings getSettings(DataSource dataSource) { + static DatabaseInitializationSettings getSettings(DataSource dataSource, JdbcChatMemoryProperties properties) { var settings = new DatabaseInitializationSettings(); settings.setSchemaLocations(resolveSchemaLocations(dataSource)); - settings.setMode(DatabaseInitializationMode.ALWAYS); + settings.setMode(properties.getInitializeSchema()); settings.setContinueOnError(true); return settings; diff --git a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryProperties.java b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryProperties.java index 1c33ffbb0a5..e079d9da60c 100644 --- a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryProperties.java +++ b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/main/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryProperties.java @@ -17,9 +17,11 @@ package org.springframework.ai.model.chat.memory.jdbc.autoconfigure; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.sql.init.DatabaseInitializationMode; /** * @author Jonathan Leijendekker + * @author Eddú Meléndez * @since 1.0.0 */ @ConfigurationProperties(JdbcChatMemoryProperties.CONFIG_PREFIX) @@ -27,13 +29,16 @@ public class JdbcChatMemoryProperties { public static final String CONFIG_PREFIX = "spring.ai.chat.memory.jdbc"; - private boolean initializeSchema = true; + /** + * Database schema initialization mode. + */ + private DatabaseInitializationMode initializeSchema = DatabaseInitializationMode.EMBEDDED; - public boolean isInitializeSchema() { + public DatabaseInitializationMode getInitializeSchema() { return this.initializeSchema; } - public void setInitializeSchema(boolean initializeSchema) { + public void setInitializeSchema(DatabaseInitializationMode initializeSchema) { this.initializeSchema = initializeSchema; } diff --git a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryAutoConfigurationIT.java b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryAutoConfigurationIT.java index 6f9573d3eb0..7c047d4be77 100644 --- a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryAutoConfigurationIT.java +++ b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryAutoConfigurationIT.java @@ -38,6 +38,7 @@ /** * @author Jonathan Leijendekker + * @author Eddú Meléndez */ @Testcontainers class JdbcChatMemoryAutoConfigurationIT { @@ -60,21 +61,21 @@ class JdbcChatMemoryAutoConfigurationIT { @Test void jdbcChatMemoryScriptDatabaseInitializer_shouldBeLoaded() { - this.contextRunner.withPropertyValues("spring.ai.chat.memory.jdbc.initialize-schema=true").run(context -> { + this.contextRunner.withPropertyValues("spring.ai.chat.memory.jdbc.initialize-schema=always").run(context -> { assertThat(context.containsBean("jdbcChatMemoryScriptDatabaseInitializer")).isTrue(); }); } @Test void jdbcChatMemoryScriptDatabaseInitializer_shouldNotBeLoaded() { - this.contextRunner.withPropertyValues("spring.ai.chat.memory.jdbc.initialize-schema=false").run(context -> { + this.contextRunner.withPropertyValues("spring.ai.chat.memory.jdbc.initialize-schema=never").run(context -> { assertThat(context.containsBean("jdbcChatMemoryScriptDatabaseInitializer")).isFalse(); }); } @Test void addGetAndClear_shouldAllExecute() { - this.contextRunner.withPropertyValues("spring.ai.chat.memory.jdbc.initialize-schema=true").run(context -> { + this.contextRunner.withPropertyValues("spring.ai.chat.memory.jdbc.initialize-schema=always").run(context -> { var chatMemory = context.getBean(JdbcChatMemory.class); var conversationId = UUID.randomUUID().toString(); var userMessage = new UserMessage("Message from the user"); diff --git a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryDataSourceScriptDatabaseInitializerTests.java b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryDataSourceScriptDatabaseInitializerTests.java index bcb1a9daacc..427192e63cc 100644 --- a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryDataSourceScriptDatabaseInitializerTests.java +++ b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryDataSourceScriptDatabaseInitializerTests.java @@ -17,6 +17,7 @@ /** * @author Jonathan Leijendekker + * @author Eddú Meléndez */ @Testcontainers class JdbcChatMemoryDataSourceScriptDatabaseInitializerTests { @@ -41,7 +42,8 @@ class JdbcChatMemoryDataSourceScriptDatabaseInitializerTests { void getSettings_shouldHaveSchemaLocations() { this.contextRunner.run(context -> { var dataSource = context.getBean(DataSource.class); - var settings = JdbcChatMemoryDataSourceScriptDatabaseInitializer.getSettings(dataSource); + var properties = context.getBean(JdbcChatMemoryProperties.class); + var settings = JdbcChatMemoryDataSourceScriptDatabaseInitializer.getSettings(dataSource, properties); assertThat(settings.getSchemaLocations()) .containsOnly("classpath:org/springframework/ai/chat/memory/jdbc/schema-postgresql.sql"); diff --git a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryPropertiesTests.java b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryPropertiesTests.java deleted file mode 100644 index 196176149ff..00000000000 --- a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryPropertiesTests.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2024-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.model.chat.memory.jdbc.autoconfigure; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Jonathan Leijendekker - */ -class JdbcChatMemoryPropertiesTests { - - @Test - void defaultValues() { - var props = new JdbcChatMemoryProperties(); - - assertThat(props.isInitializeSchema()).isTrue(); - } - - @Test - void customValues() { - var props = new JdbcChatMemoryProperties(); - props.setInitializeSchema(false); - - assertThat(props.isInitializeSchema()).isFalse(); - } - -} diff --git a/memory/spring-ai-model-chat-memory-jdbc/src/main/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemory.java b/memory/spring-ai-model-chat-memory-jdbc/src/main/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemory.java index 477f7509a19..e770ace97d2 100644 --- a/memory/spring-ai-model-chat-memory-jdbc/src/main/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemory.java +++ b/memory/spring-ai-model-chat-memory-jdbc/src/main/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemory.java @@ -37,8 +37,7 @@ */ public class JdbcChatMemory implements ChatMemory { - private static final String QUERY_ADD = """ - INSERT INTO ai_chat_memory (conversation_id, content, type) VALUES (?, ?, ?)"""; + private static final String QUERY_ADD = "INSERT INTO ai_chat_memory (conversation_id, content, type) VALUES (?, ?, ?)"; private static final String QUERY_GET = """ SELECT content, type FROM ai_chat_memory WHERE conversation_id = ? ORDER BY "timestamp" DESC LIMIT ?"""; diff --git a/memory/spring-ai-model-chat-memory-jdbc/src/test/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemoryIT.java b/memory/spring-ai-model-chat-memory-jdbc/src/test/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemoryIT.java index 1651bd49e87..f95ce1be1cd 100644 --- a/memory/spring-ai-model-chat-memory-jdbc/src/test/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemoryIT.java +++ b/memory/spring-ai-model-chat-memory-jdbc/src/test/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemoryIT.java @@ -22,7 +22,6 @@ import javax.sql.DataSource; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -47,6 +46,7 @@ /** * @author Jonathan Leijendekker + * @author Eddú Meléndez */ @Testcontainers class JdbcChatMemoryIT { @@ -67,11 +67,6 @@ class JdbcChatMemoryIT { String.format("app.datasource.username=%s", postgresContainer.getUsername()), String.format("app.datasource.password=%s", postgresContainer.getPassword())); - @BeforeAll - static void beforeAll() { - - } - @Test void correctChatMemoryInstance() { this.contextRunner.run(context -> {