Refactor chat memory repository artifacts for clarity

- Rename the artifact ID of the chat memory repository artifacts:

    - `spring-ai-model-chat-memory-jdbc` -> `spring-ai-model-chat-memory-repository-jdbc`
    - `spring-ai-model-chat-memory-cassandra` -> `spring-ai-model-chat-memory-repository-cassandra`
    - `spring-ai-model-chat-memory-neo4j` -> `spring-ai-model-chat-memory-repository-neo4j`

 - Rename the package names to include "repository". Example: org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository
    - This package renaming also requires to change the default schema location for the jdbc repository to include "repository"
      - Update the docs

 - Update the artifact IDs in the parent POM, BOM, autoconfiguration and starters
 - Update upgrade notes and docs to describe the changes

Fix JdbcChatMemoryRepositoryPostgresqlIT
 - Make sure to set the dialect via datasource

Signed-off-by: Ilayaperumal Gopinathan <ilayaperumal.gopinathan@broadcom.com>
This commit is contained in:
Ilayaperumal Gopinathan
2025-05-11 09:54:54 +01:00
committed by Mark Pollack
parent e10fbde7a1
commit 2d517eec5c
57 changed files with 119 additions and 103 deletions

View File

@@ -25,7 +25,7 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model-chat-memory-cassandra</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-cassandra</artifactId>
<version>${project.parent.version}</version>
</dependency>

View File

@@ -18,8 +18,8 @@ package org.springframework.ai.model.chat.memory.repository.cassandra.autoconfig
import com.datastax.oss.driver.api.core.CqlSession;
import org.springframework.ai.chat.memory.cassandra.CassandraChatMemoryRepositoryConfig;
import org.springframework.ai.chat.memory.cassandra.CassandraChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.cassandra.CassandraChatMemoryRepositoryConfig;
import org.springframework.ai.chat.memory.repository.cassandra.CassandraChatMemoryRepository;
import org.springframework.ai.model.chat.memory.autoconfigure.ChatMemoryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;

View File

@@ -21,7 +21,7 @@ import java.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.memory.cassandra.CassandraChatMemoryRepositoryConfig;
import org.springframework.ai.chat.memory.repository.cassandra.CassandraChatMemoryRepositoryConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.lang.Nullable;

View File

@@ -26,7 +26,7 @@ import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import org.springframework.ai.chat.memory.cassandra.CassandraChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.cassandra.CassandraChatMemoryRepository;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.MessageType;
import org.springframework.ai.chat.messages.UserMessage;

View File

@@ -20,7 +20,7 @@ import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.memory.cassandra.CassandraChatMemoryRepositoryConfig;
import org.springframework.ai.chat.memory.repository.cassandra.CassandraChatMemoryRepositoryConfig;
import static org.assertj.core.api.Assertions.assertThat;

View File

@@ -25,7 +25,7 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model-chat-memory-jdbc</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-jdbc</artifactId>
<version>${project.parent.version}</version>
</dependency>

View File

@@ -18,8 +18,8 @@ package org.springframework.ai.model.chat.memory.repository.jdbc.autoconfigure;
import javax.sql.DataSource;
import org.springframework.ai.chat.memory.jdbc.JdbcChatMemoryDialect;
import org.springframework.ai.chat.memory.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepositoryDialect;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.model.chat.memory.autoconfigure.ChatMemoryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -45,7 +45,7 @@ public class JdbcChatMemoryRepositoryAutoConfiguration {
@Bean
@ConditionalOnMissingBean
JdbcChatMemoryRepository jdbcChatMemoryRepository(JdbcTemplate jdbcTemplate, DataSource dataSource) {
JdbcChatMemoryDialect dialect = JdbcChatMemoryDialect.from(dataSource);
JdbcChatMemoryRepositoryDialect dialect = JdbcChatMemoryRepositoryDialect.from(dataSource);
return JdbcChatMemoryRepository.builder().jdbcTemplate(jdbcTemplate).dialect(dialect).build();
}

View File

@@ -30,7 +30,7 @@ public class JdbcChatMemoryRepositoryProperties {
public static final String CONFIG_PREFIX = "spring.ai.chat.memory.repository.jdbc";
private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/springframework/ai/chat/memory/jdbc/schema-@@platform@@.sql";
private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-@@platform@@.sql";
/**
* Whether to initialize the schema on startup. Values: embedded, always, never.
@@ -40,7 +40,7 @@ public class JdbcChatMemoryRepositoryProperties {
/**
* Locations of schema (DDL) scripts. Supports comma-separated list. Default is
* classpath:org/springframework/ai/chat/memory/jdbc/schema-@@platform@@.sql
* classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-@@platform@@.sql
*/
private String schema = DEFAULT_SCHEMA_LOCATION;

View File

@@ -22,6 +22,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
@@ -39,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = JdbcChatMemoryHsqldbAutoConfigurationIT.TestConfig.class,
@SpringBootTest(classes = JdbcChatMemoryRepositoryHsqldbAutoConfigurationIT.TestConfig.class,
properties = { "spring.datasource.url=jdbc:hsqldb:mem:chat_memory_auto_configuration_test;DB_CLOSE_DELAY=-1",
"spring.datasource.username=sa", "spring.datasource.password=",
"spring.datasource.driver-class-name=org.hsqldb.jdbcDriver",
@@ -54,7 +55,7 @@ import static org.assertj.core.api.Assertions.fail;
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration.class,
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class,
SqlInitializationAutoConfiguration.class })
public class JdbcChatMemoryHsqldbAutoConfigurationIT {
public class JdbcChatMemoryRepositoryHsqldbAutoConfigurationIT {
@Autowired
private ApplicationContext context;
@@ -130,7 +131,7 @@ public class JdbcChatMemoryHsqldbAutoConfigurationIT {
try {
java.util.Enumeration<java.net.URL> resources = Thread.currentThread()
.getContextClassLoader()
.getResources("org/springframework/ai/chat/memory/jdbc/schema-hsqldb.sql");
.getResources("org/springframework/ai/chat/memory/repository/jdbc/schema-hsqldb.sql");
System.out.println("--- schema-hsqldb.sql resources found on classpath ---");
while (resources.hasMoreElements()) {
System.out.println(resources.nextElement());
@@ -157,7 +158,7 @@ public class JdbcChatMemoryHsqldbAutoConfigurationIT {
// Now test the ChatMemory functionality
assertThat(context.getBean(org.springframework.ai.chat.memory.ChatMemory.class)).isNotNull();
assertThat(context.getBean(org.springframework.ai.chat.memory.jdbc.JdbcChatMemoryRepository.class)).isNotNull();
assertThat(context.getBean(JdbcChatMemoryRepository.class)).isNotNull();
var chatMemory = context.getBean(org.springframework.ai.chat.memory.ChatMemory.class);
var conversationId = java.util.UUID.randomUUID().toString();

View File

@@ -22,7 +22,7 @@ import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
@@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Linar Abzaltdinov
* @author Yanming Zhou
*/
class JdbcChatMemoryPostgresqlAutoConfigurationIT {
class JdbcChatMemoryRepositoryPostgresqlAutoConfigurationIT {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(JdbcChatMemoryRepositoryAutoConfiguration.class,

View File

@@ -62,7 +62,7 @@ class JdbcChatMemoryRepositorySchemaInitializerPostgresqlTests {
new JdbcChatMemoryRepositoryProperties());
assertThat(settings.getSchemaLocations())
.containsOnly("classpath:org/springframework/ai/chat/memory/jdbc/schema-postgresql.sql");
.containsOnly("classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-postgresql.sql");
});
}

View File

@@ -10,7 +10,7 @@ import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
@@ -27,7 +27,7 @@ import org.testcontainers.utility.DockerImageName;
import static org.assertj.core.api.Assertions.assertThat;
@Testcontainers
class JdbcChatMemorySqlServerAutoConfigurationIT {
class JdbcChatMemoryRepositorySqlServerAutoConfigurationIT {
static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName
.parse("mcr.microsoft.com/mssql/server:2022-latest");

View File

@@ -25,7 +25,7 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model-chat-memory-neo4j</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-neo4j</artifactId>
<version>${project.parent.version}</version>
</dependency>

View File

@@ -18,8 +18,8 @@ package org.springframework.ai.model.chat.memory.repository.neo4j.autoconfigure;
import org.neo4j.driver.Driver;
import org.springframework.ai.chat.memory.neo4j.Neo4jChatMemoryRepositoryConfig;
import org.springframework.ai.chat.memory.neo4j.Neo4jChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.neo4j.Neo4jChatMemoryRepositoryConfig;
import org.springframework.ai.chat.memory.repository.neo4j.Neo4jChatMemoryRepository;
import org.springframework.ai.model.chat.memory.autoconfigure.ChatMemoryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

View File

@@ -16,7 +16,7 @@
package org.springframework.ai.model.chat.memory.repository.neo4j.autoconfigure;
import org.springframework.ai.chat.memory.neo4j.Neo4jChatMemoryRepositoryConfig;
import org.springframework.ai.chat.memory.repository.neo4j.Neo4jChatMemoryRepositoryConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**

View File

@@ -18,7 +18,7 @@ package org.springframework.ai.model.chat.memory.repository.neo4j.autoconfigure;
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.memory.neo4j.Neo4jChatMemoryRepositoryConfig;
import org.springframework.ai.chat.memory.repository.neo4j.Neo4jChatMemoryRepositoryConfig;
import static org.assertj.core.api.Assertions.assertThat;

View File

@@ -25,13 +25,13 @@ import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.memory.ChatMemoryRepository;
import org.springframework.ai.chat.memory.neo4j.Neo4jChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.neo4j.Neo4jChatMemoryRepository;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import org.springframework.ai.chat.memory.neo4j.Neo4jChatMemoryRepositoryConfig;
import org.springframework.ai.chat.memory.repository.neo4j.Neo4jChatMemoryRepositoryConfig;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;

View File

@@ -23,12 +23,12 @@
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>spring-ai-model-chat-memory-cassandra</artifactId>
<name>Spring AI Apache Cassandra Chat Memory</name>
<description>Spring AI Apache Cassandra Chat Memory implementation</description>
<artifactId>spring-ai-model-chat-memory-repository-cassandra</artifactId>
<name>Spring AI Apache Cassandra Chat Memory Repository</name>
<description>Spring AI Apache Cassandra Chat Memory Repository implementation</description>
<url>https://github.com/spring-projects/spring-ai</url>

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.cassandra;
package org.springframework.ai.chat.memory.repository.cassandra;
import java.time.Instant;
import java.util.ArrayList;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.cassandra;
package org.springframework.ai.chat.memory.repository.cassandra;
import java.net.InetSocketAddress;
import java.time.Duration;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.cassandra;
package org.springframework.ai.chat.memory.repository.cassandra;
import java.time.Duration;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.cassandra;
package org.springframework.ai.chat.memory.repository.cassandra;
import java.time.Duration;
import java.util.List;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.cassandra;
package org.springframework.ai.chat.memory.repository.cassandra;
import org.testcontainers.utility.DockerImageName;

View File

@@ -23,10 +23,10 @@
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>spring-ai-model-chat-memory-jdbc</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-jdbc</artifactId>
<name>Spring AI JDBC Chat Memory</name>
<description>Spring AI JDBC Chat Memory implementation</description>

View File

@@ -14,12 +14,12 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.jdbc;
package org.springframework.ai.chat.memory.repository.jdbc;
/**
* HSQLDB-specific SQL dialect for chat memory repository.
*/
public class HsqldbChatMemoryDialect implements JdbcChatMemoryDialect {
public class HsqldbChatMemoryRepositoryDialect implements JdbcChatMemoryRepositoryDialect {
@Override
public String getSelectMessagesSql() {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.jdbc;
package org.springframework.ai.chat.memory.repository.jdbc;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -51,9 +51,9 @@ public class JdbcChatMemoryRepository implements ChatMemoryRepository {
private final JdbcTemplate jdbcTemplate;
private final JdbcChatMemoryDialect dialect;
private final JdbcChatMemoryRepositoryDialect dialect;
private JdbcChatMemoryRepository(JdbcTemplate jdbcTemplate, JdbcChatMemoryDialect dialect) {
private JdbcChatMemoryRepository(JdbcTemplate jdbcTemplate, JdbcChatMemoryRepositoryDialect dialect) {
Assert.notNull(jdbcTemplate, "jdbcTemplate cannot be null");
Assert.notNull(dialect, "dialect cannot be null");
this.jdbcTemplate = jdbcTemplate;
@@ -146,7 +146,7 @@ public class JdbcChatMemoryRepository implements ChatMemoryRepository {
private JdbcTemplate jdbcTemplate;
private JdbcChatMemoryDialect dialect;
private JdbcChatMemoryRepositoryDialect dialect;
private Builder() {
}
@@ -156,7 +156,7 @@ public class JdbcChatMemoryRepository implements ChatMemoryRepository {
return this;
}
public Builder dialect(JdbcChatMemoryDialect dialect) {
public Builder dialect(JdbcChatMemoryRepositoryDialect dialect) {
this.dialect = dialect;
return this;
}

View File

@@ -14,14 +14,14 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.jdbc;
package org.springframework.ai.chat.memory.repository.jdbc;
import javax.sql.DataSource;
/**
* Abstraction for database-specific SQL for chat memory repository.
*/
public interface JdbcChatMemoryDialect {
public interface JdbcChatMemoryRepositoryDialect {
/**
* Returns the SQL to fetch messages for a conversation, ordered by timestamp, with
@@ -51,25 +51,25 @@ public interface JdbcChatMemoryDialect {
/**
* Detects the dialect from the DataSource or JDBC URL.
*/
static JdbcChatMemoryDialect from(DataSource dataSource) {
static JdbcChatMemoryRepositoryDialect from(DataSource dataSource) {
// Simple detection (could be improved)
try {
String url = dataSource.getConnection().getMetaData().getURL().toLowerCase();
if (url.contains("postgresql"))
return new PostgresChatMemoryDialect();
return new PostgresChatMemoryRepositoryDialect();
if (url.contains("mysql"))
return new MysqlChatMemoryDialect();
return new MysqlChatMemoryRepositoryDialect();
if (url.contains("mariadb"))
return new MysqlChatMemoryDialect();
return new MysqlChatMemoryRepositoryDialect();
if (url.contains("sqlserver"))
return new SqlServerChatMemoryDialect();
return new SqlServerChatMemoryRepositoryDialect();
if (url.contains("hsqldb"))
return new HsqldbChatMemoryDialect();
return new HsqldbChatMemoryRepositoryDialect();
// Add more as needed
}
catch (Exception ignored) {
}
return new PostgresChatMemoryDialect(); // default
return new PostgresChatMemoryRepositoryDialect(); // default
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.jdbc;
package org.springframework.ai.chat.memory.repository.jdbc;
/**
* Dialect for MySQL.
@@ -22,7 +22,7 @@ package org.springframework.ai.chat.memory.jdbc;
* @author Mark Pollack
* @since 1.0.0
*/
public class MysqlChatMemoryDialect implements JdbcChatMemoryDialect {
public class MysqlChatMemoryRepositoryDialect implements JdbcChatMemoryRepositoryDialect {
@Override
public String getSelectMessagesSql() {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.jdbc;
package org.springframework.ai.chat.memory.repository.jdbc;
/**
* Dialect for Postgres.
@@ -22,7 +22,7 @@ package org.springframework.ai.chat.memory.jdbc;
* @author Mark Pollack
* @since 1.0.0
*/
public class PostgresChatMemoryDialect implements JdbcChatMemoryDialect {
public class PostgresChatMemoryRepositoryDialect implements JdbcChatMemoryRepositoryDialect {
@Override
public String getSelectMessagesSql() {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.jdbc;
package org.springframework.ai.chat.memory.repository.jdbc;
/**
* Dialect for SQL Server.
@@ -22,7 +22,7 @@ package org.springframework.ai.chat.memory.jdbc;
* @author Mark Pollack
* @since 1.0.0
*/
public class SqlServerChatMemoryDialect implements JdbcChatMemoryDialect {
public class SqlServerChatMemoryRepositoryDialect implements JdbcChatMemoryRepositoryDialect {
@Override
public String getSelectMessagesSql() {

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.jdbc.aot.hint;
package org.springframework.ai.chat.memory.repository.jdbc.aot.hint;
import javax.sql.DataSource;
@@ -34,7 +34,7 @@ class JdbcChatMemoryRepositoryRuntimeHints implements RuntimeHintsRegistrar {
hints.reflection()
.registerType(DataSource.class, hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS));
hints.resources().registerPattern("org/springframework/ai/chat/memory/jdbc/schema-*.sql");
hints.resources().registerPattern("org/springframework/ai/chat/memory/repository/jdbc/schema-*.sql");
}
}

View File

@@ -16,7 +16,7 @@
@NonNullApi
@NonNullFields
package org.springframework.ai.chat.memory.jdbc;
package org.springframework.ai.chat.memory.repository.jdbc;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

View File

@@ -0,0 +1,2 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.ai.chat.memory.repository.jdbc.aot.hint.JdbcChatMemoryRepositoryRuntimeHints

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.jdbc;
package org.springframework.ai.chat.memory.repository.jdbc;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -40,6 +40,8 @@ import java.sql.Timestamp;
import java.util.List;
import java.util.UUID;
import javax.sql.DataSource;
import static org.assertj.core.api.Assertions.assertThat;
/**
@@ -50,7 +52,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
@SpringBootTest(classes = JdbcChatMemoryRepositoryPostgresqlIT.TestConfiguration.class)
@TestPropertySource(properties = "spring.datasource.url=jdbc:tc:postgresql:17:///")
@Sql(scripts = "classpath:org/springframework/ai/chat/memory/jdbc/schema-postgresql.sql")
@Sql(scripts = "classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-postgresql.sql")
class JdbcChatMemoryRepositoryPostgresqlIT {
@Autowired
@@ -77,7 +79,7 @@ class JdbcChatMemoryRepositoryPostgresqlIT {
chatMemoryRepository.saveAll(conversationId, List.of(message));
var query = "SELECT conversation_id, content, type, \"timestamp\" FROM ai_chat_memory WHERE conversation_id = ?";
var query = "SELECT conversation_id, content, type, \"timestamp\" FROM SPRING_AI_CHAT_MEMORY WHERE conversation_id = ?";
var result = jdbcTemplate.queryForMap(query, conversationId);
assertThat(result.size()).isEqualTo(4);
@@ -96,7 +98,7 @@ class JdbcChatMemoryRepositoryPostgresqlIT {
chatMemoryRepository.saveAll(conversationId, messages);
var query = "SELECT conversation_id, content, type, \"timestamp\" FROM ai_chat_memory WHERE conversation_id = ?";
var query = "SELECT conversation_id, content, type, \"timestamp\" FROM SPRING_AI_CHAT_MEMORY WHERE conversation_id = ?";
var results = jdbcTemplate.queryForList(query, conversationId);
assertThat(results.size()).isEqualTo(messages.size());
@@ -148,7 +150,7 @@ class JdbcChatMemoryRepositoryPostgresqlIT {
chatMemoryRepository.deleteByConversationId(conversationId);
var count = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM ai_chat_memory WHERE conversation_id = ?",
var count = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM SPRING_AI_CHAT_MEMORY WHERE conversation_id = ?",
Integer.class, conversationId);
assertThat(count).isZero();
@@ -159,8 +161,11 @@ class JdbcChatMemoryRepositoryPostgresqlIT {
static class TestConfiguration {
@Bean
ChatMemoryRepository chatMemoryRepository(JdbcTemplate jdbcTemplate) {
return JdbcChatMemoryRepository.builder().jdbcTemplate(jdbcTemplate).build();
ChatMemoryRepository chatMemoryRepository(JdbcTemplate jdbcTemplate, DataSource dataSource) {
return JdbcChatMemoryRepository.builder()
.jdbcTemplate(jdbcTemplate)
.dialect(JdbcChatMemoryRepositoryDialect.from(dataSource))
.build();
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.jdbc.aot.hint;
package org.springframework.ai.chat.memory.repository.jdbc.aot.hint;
import java.io.IOException;
import java.util.Arrays;
@@ -60,7 +60,7 @@ class JdbcChatMemoryRepositoryRuntimeHintsTest {
this.jdbcChatMemoryRepositoryRuntimeHints.registerHints(this.hints, getClass().getClassLoader());
var predicate = RuntimeHintsPredicates.resource()
.forResource("org/springframework/ai/chat/memory/jdbc/" + schemaFileName);
.forResource("org/springframework/ai/chat/memory/repository/jdbc/" + schemaFileName);
assertThat(predicate).accepts(this.hints);
}
@@ -74,7 +74,7 @@ class JdbcChatMemoryRepositoryRuntimeHintsTest {
private static Stream<String> getSchemaFileNames() throws IOException {
var resources = new PathMatchingResourcePatternResolver()
.getResources("classpath*:org/springframework/ai/chat/memory/jdbc/schema-*.sql");
.getResources("classpath*:org/springframework/ai/chat/memory/repository/jdbc/schema-*.sql");
return Arrays.stream(resources).map(Resource::getFilename);
}

View File

@@ -23,12 +23,12 @@
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>spring-ai-model-chat-memory-neo4j</artifactId>
<name>Spring AI Neo4j Chat Memory</name>
<description>Spring AI Neo4j Chat Memory implementation</description>
<artifactId>spring-ai-model-chat-memory-repository-neo4j</artifactId>
<name>Spring AI Neo4j Chat Memory Repository</name>
<description>Spring AI Neo4j Chat Memory Repository implementation</description>
<url>https://github.com/spring-projects/spring-ai</url>

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.neo4j;
package org.springframework.ai.chat.memory.repository.neo4j;
/**
* @author Enrico Rampazzo

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.neo4j;
package org.springframework.ai.chat.memory.repository.neo4j;
/**
* @author Enrico Rampazzo

View File

@@ -1,4 +1,4 @@
package org.springframework.ai.chat.memory.neo4j;
package org.springframework.ai.chat.memory.repository.neo4j;
import org.neo4j.driver.Session;
import org.neo4j.driver.Transaction;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.neo4j;
package org.springframework.ai.chat.memory.repository.neo4j;
import org.neo4j.driver.Driver;
import org.slf4j.Logger;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.neo4j;
package org.springframework.ai.chat.memory.repository.neo4j;
/*
* @author Enrico Rampazzo

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.neo4j;
package org.springframework.ai.chat.memory.repository.neo4j;
/*
* @author Enrico Rampazzo

View File

@@ -1,4 +1,4 @@
package org.springframework.ai.chat.memory.neo4j;
package org.springframework.ai.chat.memory.repository.neo4j;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeAll;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.ai.chat.memory.neo4j;
package org.springframework.ai.chat.memory.repository.neo4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;

View File

@@ -1,2 +0,0 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.ai.chat.memory.jdbc.aot.hint.JdbcChatMemoryRepositoryRuntimeHints

View File

@@ -41,9 +41,9 @@
<module>spring-ai-rag</module>
<module>advisors/spring-ai-advisors-vector-store</module>
<module>memory/spring-ai-model-chat-memory-cassandra</module>
<module>memory/spring-ai-model-chat-memory-jdbc</module>
<module>memory/spring-ai-model-chat-memory-neo4j</module>
<module>memory/repository/spring-ai-model-chat-memory-repository-cassandra</module>
<module>memory/repository/spring-ai-model-chat-memory-repository-jdbc</module>
<module>memory/repository/spring-ai-model-chat-memory-repository-neo4j</module>
@@ -169,7 +169,7 @@
<module>models/spring-ai-ollama</module>
<module>models/spring-ai-openai</module>
<module>models/spring-ai-postgresml</module>
<module>models/spring-ai-stability-ai</module>
<module>models/spring-ai-stability-ai</module>
<module>models/spring-ai-transformers</module>
<module>models/spring-ai-vertex-ai-embedding</module>
<module>models/spring-ai-vertex-ai-gemini</module>

View File

@@ -206,19 +206,19 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model-chat-memory-cassandra</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-cassandra</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model-chat-memory-jdbc</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-jdbc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model-chat-memory-neo4j</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-neo4j</artifactId>
<version>${project.version}</version>
</dependency>

View File

@@ -105,7 +105,7 @@ ChatMemory chatMemory = MessageWindowChatMemory.builder()
.build();
----
If you'd rather create the `JdbcChatMemoryRepository` manually, you can do so by providing a `JdbcTemplate` instance and optionally a custom `JdbcChatMemoryDialect`:
If you'd rather create the `JdbcChatMemoryRepository` manually, you can do so by providing a `JdbcTemplate` instance and optionally a custom `JdbcChatMemoryRepositoryDialect`:
[source,java]
----
@@ -129,7 +129,7 @@ Spring AI supports multiple relational databases via a dialect abstraction. The
- SQL Server
- HSQLDB
The correct dialect is auto-detected from the JDBC URL. You can extend support for other databases by implementing the `JdbcChatMemoryDialect` interface.
The correct dialect is auto-detected from the JDBC URL. You can extend support for other databases by implementing the `JdbcChatMemoryRepositoryDialect` interface.
==== Configuration Properties
@@ -137,7 +137,7 @@ The correct dialect is auto-detected from the JDBC URL. You can extend support f
|===
|Property | Description | Default Value
| `spring.ai.chat.memory.repository.jdbc.initialize-schema` | Controls when to initialize the schema. Values: `embedded` (default), `always`, `never`. | `embedded`
| `spring.ai.chat.memory.repository.jdbc.schema` | Location of the schema script to use for initialization. Supports `classpath:` URLs and platform placeholders. | `classpath:org/springframework/ai/chat/memory/jdbc/schema-@@platform@@.sql`
| `spring.ai.chat.memory.repository.jdbc.schema` | Location of the schema script to use for initialization. Supports `classpath:` URLs and platform placeholders. | `classpath:org/springframework/ai/chat/memory/repository/jdbc/schema-@@platform@@.sql`
|===
==== Schema Initialization
@@ -162,7 +162,7 @@ spring.ai.chat.memory.repository.jdbc.schema=classpath:/custom/path/schema-mysql
==== Extending Dialects
To add support for a new database, implement the `JdbcChatMemoryDialect` interface and provide SQL for selecting, inserting, and deleting messages. You can then pass your custom dialect to the repository builder.
To add support for a new database, implement the `JdbcChatMemoryRepositoryDialect` interface and provide SQL for selecting, inserting, and deleting messages. You can then pass your custom dialect to the repository builder.
[source,java]
----

View File

@@ -60,9 +60,19 @@ Hopefully Watson will reappear in a future version of Spring AI
In 1.0.0-RC1, the chat memory modules, starters, and autoconfiguration classes for Cassandra, JDBC, and Neo4j have been renamed to include the `repository` suffix for clarity. This impacts artifact IDs, Java package names, and class names. For example:
- Artifact IDs:
- `spring-ai-model-chat-memory-jdbc` -> `spring-ai-model-chat-memory-repository-jdbc`
- `spring-ai-autoconfigure-model-chat-memory-jdbc` → `spring-ai-autoconfigure-model-chat-memory-repository-jdbc`
- `spring-ai-starter-model-chat-memory-jdbc` → `spring-ai-starter-model-chat-memory-repository-jdbc`
- Java packages now use `.repository.` (e.g., `org.springframework.ai.model.chat.memory.repository.jdbc.autoconfigure`).
- `spring-ai-model-chat-memory-cassandra` -> `spring-ai-model-chat-memory-repository-cassandra`
- `spring-ai-autoconfigure-model-chat-memory-cassandra` → `spring-ai-autoconfigure-model-chat-memory-repository-cassandra`
- `spring-ai-starter-model-chat-memory-cassandra` → `spring-ai-starter-model-chat-memory-repository-cassandra`
- `spring-ai-model-chat-memory-neo4j` -> `spring-ai-model-chat-memory-repository-neo4j`
- `spring-ai-autoconfigure-model-chat-memory-neo4j` → `spring-ai-autoconfigure-model-chat-memory-repository-neo4j`
- `spring-ai-starter-model-chat-memory-neo4j` → `spring-ai-starter-model-chat-memory-repository-neo4j`
- Java packages now use `.repository.` (e.g., `org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository` and `org.springframework.ai.model.chat.memory.repository.jdbc.autoconfigure.JdbcChatMemoryRepositoryAutoConfiguration`).
- Main autoconfiguration classes are now named `JdbcChatMemoryRepositoryAutoConfiguration`, `CassandraChatMemoryRepositoryAutoConfiguration`, etc.
**Migration Required:**

View File

@@ -56,7 +56,7 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model-chat-memory-cassandra</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-cassandra</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>

View File

@@ -56,7 +56,7 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model-chat-memory-jdbc</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-jdbc</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>

View File

@@ -56,7 +56,7 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model-chat-memory-neo4j</artifactId>
<artifactId>spring-ai-model-chat-memory-repository-neo4j</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>