diff --git a/auto-configurations/common/spring-ai-autoconfigure-retry/pom.xml b/auto-configurations/common/spring-ai-autoconfigure-retry/pom.xml
index 4fcb9371d82..e1f010d4a19 100644
--- a/auto-configurations/common/spring-ai-autoconfigure-retry/pom.xml
+++ b/auto-configurations/common/spring-ai-autoconfigure-retry/pom.xml
@@ -61,6 +61,11 @@
spring-boot-starter-test
test
+
+ org.springframework.boot
+ spring-boot-starter-restclient-test
+ test
+
org.mockito
diff --git a/auto-configurations/common/spring-ai-autoconfigure-retry/src/main/java/org/springframework/ai/retry/autoconfigure/SpringAiRetryAutoConfiguration.java b/auto-configurations/common/spring-ai-autoconfigure-retry/src/main/java/org/springframework/ai/retry/autoconfigure/SpringAiRetryAutoConfiguration.java
index 1d7eed38da9..1a1cef42d90 100644
--- a/auto-configurations/common/spring-ai-autoconfigure-retry/src/main/java/org/springframework/ai/retry/autoconfigure/SpringAiRetryAutoConfiguration.java
+++ b/auto-configurations/common/spring-ai-autoconfigure-retry/src/main/java/org/springframework/ai/retry/autoconfigure/SpringAiRetryAutoConfiguration.java
@@ -17,7 +17,9 @@
package org.springframework.ai.retry.autoconfigure;
import java.io.IOException;
+import java.net.URI;
import java.nio.charset.StandardCharsets;
+import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,12 +32,13 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
+import org.springframework.core.retry.RetryListener;
+import org.springframework.core.retry.RetryPolicy;
+import org.springframework.core.retry.RetryTemplate;
+import org.springframework.core.retry.Retryable;
+import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.NonNull;
-import org.springframework.retry.RetryCallback;
-import org.springframework.retry.RetryContext;
-import org.springframework.retry.RetryListener;
-import org.springframework.retry.support.RetryTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.ResponseErrorHandler;
@@ -58,21 +61,25 @@ public class SpringAiRetryAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RetryTemplate retryTemplate(SpringAiRetryProperties properties) {
- return RetryTemplate.builder()
+ RetryPolicy retryPolicy = RetryPolicy.builder()
.maxAttempts(properties.getMaxAttempts())
- .retryOn(TransientAiException.class)
- .exponentialBackoff(properties.getBackoff().getInitialInterval(), properties.getBackoff().getMultiplier(),
- properties.getBackoff().getMaxInterval())
- .withListener(new RetryListener() {
-
- @Override
- public void onError(RetryContext context, RetryCallback callback,
- Throwable throwable) {
- logger.warn("Retry error. Retry count: {}, Exception: {}", context.getRetryCount(),
- throwable.getMessage(), throwable);
- }
- })
+ .includes(TransientAiException.class)
+ .delay(properties.getBackoff().getInitialInterval())
+ .multiplier(properties.getBackoff().getMultiplier())
+ .maxDelay(properties.getBackoff().getMaxInterval())
.build();
+
+ RetryTemplate retryTemplate = new RetryTemplate(retryPolicy);
+ retryTemplate.setRetryListener(new RetryListener() {
+ private final AtomicInteger retryCount = new AtomicInteger(0);
+
+ @Override
+ public void onRetryFailure(RetryPolicy policy, Retryable> retryable, Throwable throwable) {
+ int currentRetries = this.retryCount.incrementAndGet();
+ logger.warn("Retry error. Retry count:{}", currentRetries, throwable);
+ }
+ });
+ return retryTemplate;
}
@Bean
@@ -87,6 +94,12 @@ public boolean hasError(@NonNull ClientHttpResponse response) throws IOException
}
@Override
+ public void handleError(@NonNull URI url, @NonNull HttpMethod method, @NonNull ClientHttpResponse response)
+ throws IOException {
+ handleError(response);
+ }
+
+ @SuppressWarnings("removal")
public void handleError(@NonNull ClientHttpResponse response) throws IOException {
if (!response.getStatusCode().isError()) {
return;
diff --git a/auto-configurations/common/spring-ai-autoconfigure-retry/src/test/java/org/springframework/ai/retry/autoconfigure/SpringAiRetryAutoConfigurationIT.java b/auto-configurations/common/spring-ai-autoconfigure-retry/src/test/java/org/springframework/ai/retry/autoconfigure/SpringAiRetryAutoConfigurationIT.java
index 4b712f0507e..dd4004dbb6b 100644
--- a/auto-configurations/common/spring-ai-autoconfigure-retry/src/test/java/org/springframework/ai/retry/autoconfigure/SpringAiRetryAutoConfigurationIT.java
+++ b/auto-configurations/common/spring-ai-autoconfigure-retry/src/test/java/org/springframework/ai/retry/autoconfigure/SpringAiRetryAutoConfigurationIT.java
@@ -19,9 +19,9 @@
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient/pom.xml b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient/pom.xml
index 62ce7340058..d7a4aae3811 100644
--- a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient/pom.xml
+++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient/pom.xml
@@ -82,7 +82,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-webflux/pom.xml b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-webflux/pom.xml
index 57341998a8c..24049480ae1 100644
--- a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-webflux/pom.xml
+++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-webflux/pom.xml
@@ -88,7 +88,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/pom.xml b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/pom.xml
index c5844c26a25..028f9e0f273 100644
--- a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/pom.xml
+++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/pom.xml
@@ -95,6 +95,17 @@
test
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-webclient
+ test
+
+
org.springframework.ai
spring-ai-autoconfigure-model-anthropic
diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpServerSseWebFluxAutoConfigurationTests.java b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpServerSseWebFluxAutoConfigurationTests.java
index 72fcafbcec6..a11eead5ec5 100644
--- a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpServerSseWebFluxAutoConfigurationTests.java
+++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/src/test/java/org/springframework/ai/mcp/server/autoconfigure/McpServerSseWebFluxAutoConfigurationTests.java
@@ -16,14 +16,15 @@
package org.springframework.ai.mcp.server.autoconfigure;
-import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider;
import org.junit.jupiter.api.Test;
+import tools.jackson.databind.DeserializationFeature;
+import tools.jackson.databind.ObjectMapper;
import org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerProperties;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
@@ -46,8 +47,7 @@ void shouldConfigureWebFluxTransportWithCustomObjectMapper() {
ObjectMapper objectMapper = context.getBean(ObjectMapper.class);
// Verify that the ObjectMapper is configured to ignore unknown properties
- assertThat(objectMapper.getDeserializationConfig()
- .isEnabled(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)).isFalse();
+ assertThat(objectMapper.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)).isFalse();
// Test with a JSON payload containing unknown fields
// CHECKSTYLE:OFF
diff --git a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/src/test/java/org/springframework/ai/mcp/server/autoconfigure/StreamableMcpAnnotationsWithLLMIT.java b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/src/test/java/org/springframework/ai/mcp/server/autoconfigure/StreamableMcpAnnotationsWithLLMIT.java
index 596f9cb20c3..bd85eb6b35f 100644
--- a/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/src/test/java/org/springframework/ai/mcp/server/autoconfigure/StreamableMcpAnnotationsWithLLMIT.java
+++ b/auto-configurations/mcp/spring-ai-autoconfigure-mcp-server-webflux/src/test/java/org/springframework/ai/mcp/server/autoconfigure/StreamableMcpAnnotationsWithLLMIT.java
@@ -65,9 +65,9 @@
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.http.server.reactive.HttpHandler;
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/pom.xml b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/pom.xml
index 9f13c6f89e9..2ebc9c1c59f 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/pom.xml
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/pom.xml
@@ -40,6 +40,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-cassandra
+
org.springframework.boot
@@ -83,13 +87,13 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
org.testcontainers
- cassandra
+ testcontainers-cassandra
test
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/src/main/java/org/springframework/ai/model/chat/memory/repository/cassandra/autoconfigure/CassandraChatMemoryRepositoryAutoConfiguration.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/src/main/java/org/springframework/ai/model/chat/memory/repository/cassandra/autoconfigure/CassandraChatMemoryRepositoryAutoConfiguration.java
index e55bc82cea5..c96330c0f69 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/src/main/java/org/springframework/ai/model/chat/memory/repository/cassandra/autoconfigure/CassandraChatMemoryRepositoryAutoConfiguration.java
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/src/main/java/org/springframework/ai/model/chat/memory/repository/cassandra/autoconfigure/CassandraChatMemoryRepositoryAutoConfiguration.java
@@ -22,9 +22,9 @@
import org.springframework.ai.chat.memory.repository.cassandra.CassandraChatMemoryRepositoryConfig;
import org.springframework.ai.model.chat.memory.autoconfigure.ChatMemoryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/src/test/java/org/springframework/ai/model/chat/memory/repository/cassandra/autoconfigure/CassandraChatMemoryRepositoryAutoConfigurationIT.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/src/test/java/org/springframework/ai/model/chat/memory/repository/cassandra/autoconfigure/CassandraChatMemoryRepositoryAutoConfigurationIT.java
index 9b619ce9039..50d04eaa3ea 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/src/test/java/org/springframework/ai/model/chat/memory/repository/cassandra/autoconfigure/CassandraChatMemoryRepositoryAutoConfigurationIT.java
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra/src/test/java/org/springframework/ai/model/chat/memory/repository/cassandra/autoconfigure/CassandraChatMemoryRepositoryAutoConfigurationIT.java
@@ -31,7 +31,7 @@
import org.springframework.ai.chat.messages.MessageType;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
+import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cosmos-db/pom.xml b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cosmos-db/pom.xml
index 535fd9f44ed..da7cb85c488 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cosmos-db/pom.xml
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cosmos-db/pom.xml
@@ -81,6 +81,11 @@
${azure-identity.version}
+
+ org.slf4j
+ jcl-over-slf4j
+
+
org.springframework.boot
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/pom.xml b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/pom.xml
index 1ffcc2f324f..a942e7b080e 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/pom.xml
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/pom.xml
@@ -40,6 +40,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
org.springframework.boot
@@ -59,6 +63,11 @@
spring-boot-starter-test
test
+
+ org.springframework.boot
+ spring-boot-starter-jdbc-test
+ test
+
org.postgresql
@@ -68,13 +77,13 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
org.testcontainers
- postgresql
+ testcontainers-postgresql
test
@@ -85,7 +94,7 @@
org.testcontainers
- mssqlserver
+ testcontainers-mssqlserver
test
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryAutoConfiguration.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryAutoConfiguration.java
index 17bed069754..5d916b1aa79 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryAutoConfiguration.java
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryAutoConfiguration.java
@@ -24,9 +24,9 @@
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.jdbc.JdbcTemplateAutoConfiguration;
-import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
+import org.springframework.boot.sql.autoconfigure.init.OnDatabaseInitializationCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryHsqldbAutoConfigurationIT.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryHsqldbAutoConfigurationIT.java
index abfd6927a46..7eed5b474ac 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryHsqldbAutoConfigurationIT.java
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryHsqldbAutoConfigurationIT.java
@@ -29,8 +29,9 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
-import org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration;
-import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
+import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -51,10 +52,8 @@
"logging.level.org.springframework.boot.sql.init=DEBUG" })
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
@ImportAutoConfiguration({ org.springframework.ai.model.chat.memory.autoconfigure.ChatMemoryAutoConfiguration.class,
- JdbcChatMemoryRepositoryAutoConfiguration.class,
- org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration.class,
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.class,
- SqlInitializationAutoConfiguration.class })
+ JdbcChatMemoryRepositoryAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
+ DataSourceAutoConfiguration.class })
public class JdbcChatMemoryRepositoryHsqldbAutoConfigurationIT {
@Autowired
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryPostgresqlAutoConfigurationIT.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryPostgresqlAutoConfigurationIT.java
index c6bde91fff4..2f7217c6710 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryPostgresqlAutoConfigurationIT.java
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositoryPostgresqlAutoConfigurationIT.java
@@ -28,8 +28,8 @@
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.model.chat.memory.autoconfigure.ChatMemoryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositorySchemaInitializerPostgresqlTests.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositorySchemaInitializerPostgresqlTests.java
index 03542a87d98..7845ef2fa95 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositorySchemaInitializerPostgresqlTests.java
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositorySchemaInitializerPostgresqlTests.java
@@ -25,8 +25,8 @@
import org.testcontainers.utility.DockerImageName;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositorySqlServerAutoConfigurationIT.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositorySqlServerAutoConfigurationIT.java
index a3bf69410ac..77095de4216 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositorySqlServerAutoConfigurationIT.java
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/model/chat/memory/repository/jdbc/autoconfigure/JdbcChatMemoryRepositorySqlServerAutoConfigurationIT.java
@@ -33,8 +33,8 @@
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.model.chat.memory.autoconfigure.ChatMemoryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/pom.xml b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/pom.xml
index dc0e1ef9373..74377bfe39f 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/pom.xml
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/pom.xml
@@ -40,6 +40,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-neo4j
+
org.springframework.boot
@@ -83,13 +87,13 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
org.testcontainers
- neo4j
+ testcontainers-neo4j
test
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/src/main/java/org/springframework/ai/model/chat/memory/repository/neo4j/autoconfigure/Neo4jChatMemoryRepositoryAutoConfiguration.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/src/main/java/org/springframework/ai/model/chat/memory/repository/neo4j/autoconfigure/Neo4jChatMemoryRepositoryAutoConfiguration.java
index 970cb6be91c..2de15fd2482 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/src/main/java/org/springframework/ai/model/chat/memory/repository/neo4j/autoconfigure/Neo4jChatMemoryRepositoryAutoConfiguration.java
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/src/main/java/org/springframework/ai/model/chat/memory/repository/neo4j/autoconfigure/Neo4jChatMemoryRepositoryAutoConfiguration.java
@@ -24,8 +24,8 @@
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.neo4j.Neo4jAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.neo4j.autoconfigure.Neo4jAutoConfiguration;
import org.springframework.context.annotation.Bean;
/**
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/src/test/java/org/springframework/ai/model/chat/memory/repository/neo4j/autoconfigure/Neo4jChatMemoryRepositoryAutoConfigurationIT.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/src/test/java/org/springframework/ai/model/chat/memory/repository/neo4j/autoconfigure/Neo4jChatMemoryRepositoryAutoConfigurationIT.java
index f60f6f61320..0ba45f83161 100644
--- a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/src/test/java/org/springframework/ai/model/chat/memory/repository/neo4j/autoconfigure/Neo4jChatMemoryRepositoryAutoConfigurationIT.java
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j/src/test/java/org/springframework/ai/model/chat/memory/repository/neo4j/autoconfigure/Neo4jChatMemoryRepositoryAutoConfigurationIT.java
@@ -39,7 +39,7 @@
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.content.Media;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
+import org.springframework.boot.neo4j.autoconfigure.Neo4jAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.util.MimeType;
diff --git a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory/pom.xml b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory/pom.xml
index 5e3ae7629fa..0c071cf380d 100644
--- a/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory/pom.xml
+++ b/auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory/pom.xml
@@ -56,7 +56,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/pom.xml
index 3835531828c..0eee243a13f 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/pom.xml
@@ -60,6 +60,17 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-webclient
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfiguration.java
index 3233dd1eee1..0ec1bf2636f 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/main/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfiguration.java
@@ -33,12 +33,12 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java
index f87eb430dfe..20af04ded1c 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicPropertiesTests.java
@@ -22,7 +22,7 @@
import org.springframework.ai.anthropic.api.AnthropicApi.ToolChoiceTool;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/BaseAnthropicIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/BaseAnthropicIT.java
index c68d9188e10..44282b3614d 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/BaseAnthropicIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/BaseAnthropicIT.java
@@ -22,8 +22,8 @@
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
public abstract class BaseAnthropicIT {
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/pom.xml
index 2f36a8c976e..9591e86c7fa 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/pom.xml
@@ -60,6 +60,17 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-webclient
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
@@ -72,6 +83,12 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+ true
+
+
org.springframework.ai
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/main/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/main/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekChatAutoConfiguration.java
index 98aae30a232..eb84d57ee65 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/main/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekChatAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/main/java/org/springframework/ai/model/deepseek/autoconfigure/DeepSeekChatAutoConfiguration.java
@@ -34,11 +34,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/BaseDeepSeekIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/BaseDeepSeekIT.java
index 9423542a624..1ea7baf7292 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/BaseDeepSeekIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-deepseek/src/test/java/org/springframework/ai/model/deepseek/autoconfigure/BaseDeepSeekIT.java
@@ -22,8 +22,8 @@
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
/**
* Base utility class for DeepSeek integration tests.
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/pom.xml
index bc09ef1f5b4..af77303b055 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/pom.xml
@@ -54,6 +54,17 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-webclient
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/main/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/main/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsAutoConfiguration.java
index bbff2dcf71e..ad0c20eecf5 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/main/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/main/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsAutoConfiguration.java
@@ -24,11 +24,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsITUtil.java b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsITUtil.java
index 9cd2b178856..86debc54233 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsITUtil.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-elevenlabs/src/test/java/org/springframework/ai/model/elevenlabs/autoconfigure/ElevenLabsITUtil.java
@@ -18,8 +18,8 @@
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
/**
* Utility class for ElevenLabs integration tests.
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/pom.xml
index 8bed6c0ea18..2a6b56d4866 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/pom.xml
@@ -74,6 +74,11 @@
spring-boot-starter
true
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
org.springframework.boot
@@ -109,13 +114,13 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
org.testcontainers
- ollama
+ testcontainers-ollama
test
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/main/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/main/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiChatAutoConfiguration.java
index e8c9b8ea2d1..664b1e3b9be 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/main/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiChatAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/main/java/org/springframework/ai/model/google/genai/autoconfigure/chat/GoogleGenAiChatAutoConfiguration.java
@@ -42,7 +42,7 @@
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/main/java/org/springframework/ai/model/google/genai/autoconfigure/embedding/GoogleGenAiTextEmbeddingAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/main/java/org/springframework/ai/model/google/genai/autoconfigure/embedding/GoogleGenAiTextEmbeddingAutoConfiguration.java
index 6fd62c663e4..d3825836171 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/main/java/org/springframework/ai/model/google/genai/autoconfigure/embedding/GoogleGenAiTextEmbeddingAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/main/java/org/springframework/ai/model/google/genai/autoconfigure/embedding/GoogleGenAiTextEmbeddingAutoConfiguration.java
@@ -31,7 +31,7 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
/**
* Auto-configuration for Google GenAI Text Embedding.
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionBeanIT.java
index 328e742fcfa..84d5bf71cc7 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionBeanIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-google-genai/src/test/java/org/springframework/ai/model/google/genai/autoconfigure/chat/tool/FunctionCallWithFunctionBeanIT.java
@@ -30,7 +30,7 @@
import org.springframework.ai.model.google.genai.autoconfigure.BaseGoogleGenAiIT;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.function.FunctionToolCallback;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/pom.xml
index 62eff8604f9..2db17c4130b 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/pom.xml
@@ -66,6 +66,12 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/main/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/main/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxChatAutoConfiguration.java
index b51445491f5..7cebce533fd 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/main/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxChatAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/main/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxChatAutoConfiguration.java
@@ -33,10 +33,10 @@
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.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/main/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxEmbeddingAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/main/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxEmbeddingAutoConfiguration.java
index e7098339cc2..36e3a82cb00 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/main/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxEmbeddingAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/main/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxEmbeddingAutoConfiguration.java
@@ -29,10 +29,10 @@
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.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackInPromptIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackInPromptIT.java
index dcf772a0bf7..16b5f011ee5 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackInPromptIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackInPromptIT.java
@@ -36,7 +36,7 @@
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackWithPlainFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackWithPlainFunctionBeanIT.java
index 0cb23c746a9..94f0678789c 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackWithPlainFunctionBeanIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/FunctionCallbackWithPlainFunctionBeanIT.java
@@ -37,7 +37,7 @@
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxAutoConfigurationIT.java
index 543ad444578..723e800e0c2 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxAutoConfigurationIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxAutoConfigurationIT.java
@@ -34,7 +34,7 @@
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxFunctionCallbackIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxFunctionCallbackIT.java
index 8e41a0641dd..956c3dcedd1 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxFunctionCallbackIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxFunctionCallbackIT.java
@@ -36,7 +36,7 @@
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxPropertiesTests.java
index c0751d5e334..44df03c8b7a 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxPropertiesTests.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MiniMaxPropertiesTests.java
@@ -27,7 +27,7 @@
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MinimaxModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MinimaxModelConfigurationTests.java
index cf1b622d1ff..6fa8ac46c54 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MinimaxModelConfigurationTests.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-minimax/src/test/java/org/springframework/ai/model/minimax/autoconfigure/MinimaxModelConfigurationTests.java
@@ -23,7 +23,7 @@
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/pom.xml
index d4642a87308..d93f1d3cd21 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/pom.xml
@@ -72,6 +72,17 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-webclient
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiChatAutoConfiguration.java
index 9044e82cbbd..8ae982b503f 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiChatAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiChatAutoConfiguration.java
@@ -33,11 +33,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiEmbeddingAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiEmbeddingAutoConfiguration.java
index ad8a8632ccd..efa30bedd9d 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiEmbeddingAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiEmbeddingAutoConfiguration.java
@@ -29,10 +29,10 @@
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.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiModerationAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiModerationAutoConfiguration.java
index 778d267019e..cb9d89db164 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiModerationAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiModerationAutoConfiguration.java
@@ -27,11 +27,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfiguration.java
index 8a247672507..4a92b82b015 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/main/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrAutoConfiguration.java
@@ -24,8 +24,8 @@
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.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrPropertiesTests.java
index 3b494c7f713..1a2ec9a34e5 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrPropertiesTests.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-mistral-ai/src/test/java/org/springframework/ai/model/mistralai/autoconfigure/MistralAiOcrPropertiesTests.java
@@ -21,7 +21,7 @@
import org.springframework.ai.mistralai.ocr.MistralOcrApi;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/pom.xml
index ecb49ce4c23..4bbe9e5574f 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/pom.xml
@@ -66,6 +66,17 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-webclient
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
@@ -100,13 +111,13 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
org.testcontainers
- ollama
+ testcontainers-ollama
test
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/main/java/org/springframework/ai/model/ollama/autoconfigure/OllamaApiAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/main/java/org/springframework/ai/model/ollama/autoconfigure/OllamaApiAutoConfiguration.java
index ed30d787021..3df440cdc3f 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/main/java/org/springframework/ai/model/ollama/autoconfigure/OllamaApiAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/main/java/org/springframework/ai/model/ollama/autoconfigure/OllamaApiAutoConfiguration.java
@@ -22,9 +22,9 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/main/java/org/springframework/ai/model/ollama/autoconfigure/OllamaChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/main/java/org/springframework/ai/model/ollama/autoconfigure/OllamaChatAutoConfiguration.java
index 34b9ad58346..67bdae15714 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/main/java/org/springframework/ai/model/ollama/autoconfigure/OllamaChatAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/main/java/org/springframework/ai/model/ollama/autoconfigure/OllamaChatAutoConfiguration.java
@@ -36,7 +36,7 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
/**
* {@link AutoConfiguration Auto-configuration} for Ollama Chat model.
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/test/java/org/springframework/ai/model/ollama/autoconfigure/BaseOllamaIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/test/java/org/springframework/ai/model/ollama/autoconfigure/BaseOllamaIT.java
index 9a3bc2527f4..681e9b0a93b 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/test/java/org/springframework/ai/model/ollama/autoconfigure/BaseOllamaIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-ollama/src/test/java/org/springframework/ai/model/ollama/autoconfigure/BaseOllamaIT.java
@@ -30,7 +30,7 @@
import org.springframework.ai.ollama.management.PullModelStrategy;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.util.Assert;
@Testcontainers
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-openai/pom.xml
index ed37e511925..548e9c9d551 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/pom.xml
@@ -71,6 +71,17 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-webclient
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAIAutoConfigurationUtil.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAIAutoConfigurationUtil.java
index 7eff1898fa4..2447478f4fd 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAIAutoConfigurationUtil.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAIAutoConfigurationUtil.java
@@ -16,14 +16,9 @@
package org.springframework.ai.model.openai.autoconfigure;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
+import org.springframework.http.HttpHeaders;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
public final class OpenAIAutoConfigurationUtil {
@@ -44,12 +39,12 @@ private OpenAIAutoConfigurationUtil() {
String organizationId = StringUtils.hasText(modelProperties.getOrganizationId())
? modelProperties.getOrganizationId() : commonProperties.getOrganizationId();
- Map> connectionHeaders = new HashMap<>();
+ HttpHeaders connectionHeaders = new HttpHeaders();
if (StringUtils.hasText(projectId)) {
- connectionHeaders.put("OpenAI-Project", List.of(projectId));
+ connectionHeaders.add("OpenAI-Project", projectId);
}
if (StringUtils.hasText(organizationId)) {
- connectionHeaders.put("OpenAI-Organization", List.of(organizationId));
+ connectionHeaders.add("OpenAI-Organization", organizationId);
}
Assert.hasText(baseUrl,
@@ -59,10 +54,10 @@ private OpenAIAutoConfigurationUtil() {
"OpenAI API key must be set. Use the connection property: spring.ai.openai.api-key or spring.ai.openai."
+ modelType + ".api-key property.");
- return new ResolvedConnectionProperties(baseUrl, apiKey, CollectionUtils.toMultiValueMap(connectionHeaders));
+ return new ResolvedConnectionProperties(baseUrl, apiKey, connectionHeaders);
}
- public record ResolvedConnectionProperties(String baseUrl, String apiKey, MultiValueMap headers) {
+ public record ResolvedConnectionProperties(String baseUrl, String apiKey, HttpHeaders headers) {
}
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioSpeechAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioSpeechAutoConfiguration.java
index 4d197904e5d..a4623072f90 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioSpeechAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioSpeechAutoConfiguration.java
@@ -28,11 +28,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioTranscriptionAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioTranscriptionAutoConfiguration.java
index 7e9b67c70ca..acba2f5d927 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioTranscriptionAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioTranscriptionAutoConfiguration.java
@@ -28,11 +28,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.java
index f1c1e4ea618..f8f5f801a11 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiChatAutoConfiguration.java
@@ -34,11 +34,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiEmbeddingAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiEmbeddingAutoConfiguration.java
index bf9b40e7a65..ac85dbdc248 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiEmbeddingAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiEmbeddingAutoConfiguration.java
@@ -30,11 +30,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageAutoConfiguration.java
index 07da6969a70..ba7ee1f8c11 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiImageAutoConfiguration.java
@@ -31,11 +31,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModerationAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModerationAutoConfiguration.java
index bf74afe8fdc..f844f4d5ec8 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModerationAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModerationAutoConfiguration.java
@@ -28,11 +28,11 @@
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.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java
index 46dec5cb44c..89bd4f3e373 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/ChatClientAutoConfigurationIT.java
@@ -29,7 +29,7 @@
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAutoConfigurationIT.java
index 78e920f7f08..93341ec43ca 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAutoConfigurationIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAutoConfigurationIT.java
@@ -42,9 +42,9 @@
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java
index b5797172932..b4c25940ddb 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiModelConfigurationTests.java
@@ -28,9 +28,9 @@
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java
index da577eed1ab..a172cfad685 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java
@@ -32,9 +32,9 @@
import org.springframework.ai.openai.api.OpenAiAudioApi;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiResponseFormatPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiResponseFormatPropertiesTests.java
index 04c2b5813f4..e36e6cc4812 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiResponseFormatPropertiesTests.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiResponseFormatPropertiesTests.java
@@ -28,9 +28,9 @@
import org.springframework.ai.openai.api.ResponseFormat;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java
index d7b90d853ff..6797d39afa0 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPrompt2IT.java
@@ -33,7 +33,7 @@
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPromptIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPromptIT.java
index 06510dfcdbe..60d47c834ce 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPromptIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackInPromptIT.java
@@ -38,7 +38,7 @@
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java
index 75debfb1069..fccf6708afd 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/FunctionCallbackWithPlainFunctionBeanIT.java
@@ -47,7 +47,7 @@
import org.springframework.ai.openai.api.OpenAiApi.ChatModel;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java
index a996c4c3e5a..4d7ed8a7459 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallback2IT.java
@@ -32,7 +32,7 @@
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallbackIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallbackIT.java
index 9c917b25fdc..0d74ddc297b 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallbackIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/tool/OpenAiFunctionCallbackIT.java
@@ -39,7 +39,7 @@
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/pom.xml
index 5ff82851c32..d4d50b6e20b 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/pom.xml
@@ -53,6 +53,11 @@
spring-boot-starter
true
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+ true
+
org.springframework.boot
@@ -79,6 +84,11 @@
spring-boot-starter-test
test
+
+ org.springframework.boot
+ spring-boot-starter-jdbc-test
+ true
+
org.springframework.boot
@@ -88,13 +98,13 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
org.testcontainers
- postgresql
+ testcontainers-postgresql
test
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/src/main/java/org/springframework/ai/model/postgresml/autoconfigure/PostgresMlEmbeddingAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/src/main/java/org/springframework/ai/model/postgresml/autoconfigure/PostgresMlEmbeddingAutoConfiguration.java
index 6fcbb4f2949..65d224ab9df 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/src/main/java/org/springframework/ai/model/postgresml/autoconfigure/PostgresMlEmbeddingAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/src/main/java/org/springframework/ai/model/postgresml/autoconfigure/PostgresMlEmbeddingAutoConfiguration.java
@@ -23,8 +23,8 @@
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.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/src/test/java/org/springframework/ai/model/postgresml/autoconfigure/PostgresMlEmbeddingAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/src/test/java/org/springframework/ai/model/postgresml/autoconfigure/PostgresMlEmbeddingAutoConfigurationIT.java
index cb7f54b829a..792ccc8f5a1 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/src/test/java/org/springframework/ai/model/postgresml/autoconfigure/PostgresMlEmbeddingAutoConfigurationIT.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-postgresml-embedding/src/test/java/org/springframework/ai/model/postgresml/autoconfigure/PostgresMlEmbeddingAutoConfigurationIT.java
@@ -30,8 +30,8 @@
import org.springframework.ai.postgresml.PostgresMlEmbeddingModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
-import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
+import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase;
+import org.springframework.boot.jdbc.test.autoconfigure.JdbcTest;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-stability-ai/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-stability-ai/pom.xml
index 38f9f644b8c..107405ef433 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-stability-ai/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-stability-ai/pom.xml
@@ -54,6 +54,12 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-stability-ai/src/main/java/org/springframework/ai/model/stabilityai/autoconfigure/StabilityAiImageAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-stability-ai/src/main/java/org/springframework/ai/model/stabilityai/autoconfigure/StabilityAiImageAutoConfiguration.java
index 119f00c2309..70833cf572a 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-stability-ai/src/main/java/org/springframework/ai/model/stabilityai/autoconfigure/StabilityAiImageAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-stability-ai/src/main/java/org/springframework/ai/model/stabilityai/autoconfigure/StabilityAiImageAutoConfiguration.java
@@ -25,8 +25,8 @@
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.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/pom.xml
index bc9593a6ffc..3ff975240ad 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/pom.xml
@@ -109,13 +109,13 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
org.testcontainers
- ollama
+ testcontainers-ollama
test
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/main/java/org/springframework/ai/model/vertexai/autoconfigure/embedding/VertexAiTextEmbeddingAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/main/java/org/springframework/ai/model/vertexai/autoconfigure/embedding/VertexAiTextEmbeddingAutoConfiguration.java
index 56e253dc2d2..8c0370ec84d 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/main/java/org/springframework/ai/model/vertexai/autoconfigure/embedding/VertexAiTextEmbeddingAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/main/java/org/springframework/ai/model/vertexai/autoconfigure/embedding/VertexAiTextEmbeddingAutoConfiguration.java
@@ -31,7 +31,7 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
/**
* Auto-configuration for Vertex AI Gemini Chat.
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/main/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiGeminiChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/main/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiGeminiChatAutoConfiguration.java
index edb7057c1e6..79b4865ca8e 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/main/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiGeminiChatAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-vertex-ai/src/main/java/org/springframework/ai/model/vertexai/autoconfigure/gemini/VertexAiGeminiChatAutoConfiguration.java
@@ -39,7 +39,7 @@
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/pom.xml b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/pom.xml
index eafc77142fa..92811dcf397 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/pom.xml
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/pom.xml
@@ -72,6 +72,12 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiChatAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiChatAutoConfiguration.java
index ba9468e5c4f..4023978c697 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiChatAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiChatAutoConfiguration.java
@@ -34,10 +34,10 @@
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.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiEmbeddingAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiEmbeddingAutoConfiguration.java
index a80913cdd3d..94ab54dfda9 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiEmbeddingAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiEmbeddingAutoConfiguration.java
@@ -30,10 +30,10 @@
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.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiImageAutoConfiguration.java b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiImageAutoConfiguration.java
index ea89f6198cb..d1e876f2afd 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiImageAutoConfiguration.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/main/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiImageAutoConfiguration.java
@@ -27,10 +27,10 @@
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.web.client.RestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiITUtil.java b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiITUtil.java
index 6c4c0833602..4df8c382ac5 100644
--- a/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiITUtil.java
+++ b/auto-configurations/models/spring-ai-autoconfigure-model-zhipuai/src/test/java/org/springframework/ai/model/zhipuai/autoconfigure/ZhiPuAiITUtil.java
@@ -19,7 +19,7 @@
import org.springframework.ai.model.tool.autoconfigure.ToolCallingAutoConfiguration;
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
/**
* Utility class for ZhiPuAI integration tests.
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/pom.xml
index dfed881e4de..0f48b2b583c 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/pom.xml
@@ -49,6 +49,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-cassandra
+
org.springframework.boot
spring-boot-configuration-processor
@@ -83,7 +87,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +97,7 @@
org.testcontainers
- cassandra
+ testcontainers-cassandra
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfiguration.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfiguration.java
index e58ef033ce9..c695b9743eb 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfiguration.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfiguration.java
@@ -30,11 +30,11 @@
import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
-import org.springframework.boot.autoconfigure.cassandra.DriverConfigLoaderBuilderCustomizer;
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.cassandra.autoconfigure.CassandraAutoConfiguration;
+import org.springframework.boot.cassandra.autoconfigure.DriverConfigLoaderBuilderCustomizer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/test/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/test/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfigurationIT.java
index 0ad388a5b60..7669a6266b5 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/test/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/test/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfigurationIT.java
@@ -37,7 +37,7 @@
import org.springframework.ai.vectorstore.cassandra.CassandraVectorStore;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
+import org.springframework.boot.cassandra.autoconfigure.CassandraAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-chroma/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-chroma/pom.xml
index a92a8d6488b..5f5ef5a74d3 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-chroma/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-chroma/pom.xml
@@ -83,7 +83,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +93,7 @@
org.testcontainers
- chromadb
+ testcontainers-chromadb
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/pom.xml
index 11e93742d7e..b60db802756 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/pom.xml
@@ -49,6 +49,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-couchbase
+
org.springframework.boot
spring-boot-configuration-processor
@@ -83,7 +87,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +97,7 @@
org.testcontainers
- couchbase
+ testcontainers-couchbase
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/src/main/java/org/springframework/ai/vectorstore/couchbase/autoconfigure/CouchbaseSearchVectorStoreAutoConfiguration.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/src/main/java/org/springframework/ai/vectorstore/couchbase/autoconfigure/CouchbaseSearchVectorStoreAutoConfiguration.java
index 25aa0617930..63e31484166 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/src/main/java/org/springframework/ai/vectorstore/couchbase/autoconfigure/CouchbaseSearchVectorStoreAutoConfiguration.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/src/main/java/org/springframework/ai/vectorstore/couchbase/autoconfigure/CouchbaseSearchVectorStoreAutoConfiguration.java
@@ -23,9 +23,9 @@
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.couchbase.CouchbaseAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
+import org.springframework.boot.couchbase.autoconfigure.CouchbaseAutoConfiguration;
import org.springframework.context.annotation.Bean;
/**
@@ -49,9 +49,9 @@ public CouchbaseSearchVectorStore vectorStore(CouchbaseSearchVectorStoreProperti
mapper.from(properties::getBucketName).whenHasText().to(builder::bucketName);
mapper.from(properties::getScopeName).whenHasText().to(builder::scopeName);
mapper.from(properties::getCollectionName).whenHasText().to(builder::collectionName);
- mapper.from(properties::getDimensions).whenNonNull().to(builder::dimensions);
- mapper.from(properties::getSimilarity).whenNonNull().to(builder::similarityFunction);
- mapper.from(properties::getOptimization).whenNonNull().to(builder::indexOptimization);
+ mapper.from(properties::getDimensions).to(builder::dimensions);
+ mapper.from(properties::getSimilarity).to(builder::similarityFunction);
+ mapper.from(properties::getOptimization).to(builder::indexOptimization);
return builder.initializeSchema(properties.isInitializeSchema()).build();
}
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/src/test/java/org/springframework/ai/vectorstore/couchbase/autoconfigure/CouchbaseSearchVectorStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/src/test/java/org/springframework/ai/vectorstore/couchbase/autoconfigure/CouchbaseSearchVectorStoreAutoConfigurationIT.java
index bb8cc8b646c..902f44353a5 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/src/test/java/org/springframework/ai/vectorstore/couchbase/autoconfigure/CouchbaseSearchVectorStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-couchbase/src/test/java/org/springframework/ai/vectorstore/couchbase/autoconfigure/CouchbaseSearchVectorStoreAutoConfigurationIT.java
@@ -36,8 +36,7 @@
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.couchbase.autoconfigure.CouchbaseAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
@@ -64,8 +63,8 @@ class CouchbaseSearchVectorStoreAutoConfigurationIT {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(CouchbaseAutoConfiguration.class,
- CouchbaseSearchVectorStoreAutoConfiguration.class, RestClientAutoConfiguration.class,
- SpringAiRetryAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class))
+ CouchbaseSearchVectorStoreAutoConfiguration.class, SpringAiRetryAutoConfiguration.class,
+ OpenAiEmbeddingAutoConfiguration.class))
.withPropertyValues("spring.couchbase.connection-string=" + couchbaseContainer.getConnectionString(),
"spring.couchbase.username=" + couchbaseContainer.getUsername(),
"spring.couchbase.password=" + couchbaseContainer.getPassword(),
@@ -113,8 +112,8 @@ public void addAndSearchWithFilters() {
public void propertiesTest() {
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(CouchbaseAutoConfiguration.class,
- CouchbaseSearchVectorStoreAutoConfiguration.class, RestClientAutoConfiguration.class,
- SpringAiRetryAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class))
+ CouchbaseSearchVectorStoreAutoConfiguration.class, SpringAiRetryAutoConfiguration.class,
+ OpenAiEmbeddingAutoConfiguration.class))
.withPropertyValues("spring.couchbase.connection-string=" + couchbaseContainer.getConnectionString(),
"spring.couchbase.username=" + couchbaseContainer.getUsername(),
"spring.couchbase.password=" + couchbaseContainer.getPassword(),
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/pom.xml
index 30ab3d801c4..807bed275ea 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/pom.xml
@@ -49,6 +49,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-elasticsearch
+
org.springframework.boot
spring-boot-configuration-processor
@@ -83,7 +87,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +97,7 @@
org.testcontainers
- elasticsearch
+ testcontainers-elasticsearch
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/src/main/java/org/springframework/ai/vectorstore/elasticsearch/autoconfigure/ElasticsearchVectorStoreAutoConfiguration.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/src/main/java/org/springframework/ai/vectorstore/elasticsearch/autoconfigure/ElasticsearchVectorStoreAutoConfiguration.java
index 2c780c94f54..21d9520ea9a 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/src/main/java/org/springframework/ai/vectorstore/elasticsearch/autoconfigure/ElasticsearchVectorStoreAutoConfiguration.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/src/main/java/org/springframework/ai/vectorstore/elasticsearch/autoconfigure/ElasticsearchVectorStoreAutoConfiguration.java
@@ -16,8 +16,8 @@
package org.springframework.ai.vectorstore.elasticsearch.autoconfigure;
+import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
import io.micrometer.observation.ObservationRegistry;
-import org.elasticsearch.client.RestClient;
import org.springframework.ai.embedding.BatchingStrategy;
import org.springframework.ai.embedding.EmbeddingModel;
@@ -31,9 +31,9 @@
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.elasticsearch.ElasticsearchRestClientAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
+import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration;
import org.springframework.context.annotation.Bean;
/**
@@ -49,7 +49,7 @@
* @since 1.0.0
*/
@AutoConfiguration(after = ElasticsearchRestClientAutoConfiguration.class)
-@ConditionalOnClass({ ElasticsearchVectorStore.class, EmbeddingModel.class, RestClient.class })
+@ConditionalOnClass({ ElasticsearchVectorStore.class, EmbeddingModel.class, Rest5Client.class })
@EnableConfigurationProperties(ElasticsearchVectorStoreProperties.class)
@ConditionalOnProperty(name = SpringAIVectorStoreTypes.TYPE, havingValue = SpringAIVectorStoreTypes.ELASTICSEARCH,
matchIfMissing = true)
@@ -63,7 +63,7 @@ BatchingStrategy batchingStrategy() {
@Bean
@ConditionalOnMissingBean
- ElasticsearchVectorStore vectorStore(ElasticsearchVectorStoreProperties properties, RestClient restClient,
+ ElasticsearchVectorStore vectorStore(ElasticsearchVectorStoreProperties properties, Rest5Client restClient,
EmbeddingModel embeddingModel, ObjectProvider observationRegistry,
ObjectProvider customObservationConvention,
BatchingStrategy batchingStrategy) {
@@ -71,8 +71,8 @@ ElasticsearchVectorStore vectorStore(ElasticsearchVectorStoreProperties properti
PropertyMapper mapper = PropertyMapper.get();
mapper.from(properties::getIndexName).whenHasText().to(elasticsearchVectorStoreOptions::setIndexName);
- mapper.from(properties::getDimensions).whenNonNull().to(elasticsearchVectorStoreOptions::setDimensions);
- mapper.from(properties::getSimilarity).whenNonNull().to(elasticsearchVectorStoreOptions::setSimilarity);
+ mapper.from(properties::getDimensions).to(elasticsearchVectorStoreOptions::setDimensions);
+ mapper.from(properties::getSimilarity).to(elasticsearchVectorStoreOptions::setSimilarity);
mapper.from(properties::getEmbeddingFieldName)
.whenHasText()
.to(elasticsearchVectorStoreOptions::setEmbeddingFieldName);
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/src/test/java/org/springframework/ai/vectorstore/elasticsearch/autoconfigure/ElasticsearchVectorStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/src/test/java/org/springframework/ai/vectorstore/elasticsearch/autoconfigure/ElasticsearchVectorStoreAutoConfigurationIT.java
index dd49c2d1599..cadbc42e6cc 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/src/test/java/org/springframework/ai/vectorstore/elasticsearch/autoconfigure/ElasticsearchVectorStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-elasticsearch/src/test/java/org/springframework/ai/vectorstore/elasticsearch/autoconfigure/ElasticsearchVectorStoreAutoConfigurationIT.java
@@ -42,8 +42,7 @@
import org.springframework.ai.vectorstore.elasticsearch.SimilarityFunction;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -58,13 +57,13 @@ class ElasticsearchVectorStoreAutoConfigurationIT {
@Container
private static final ElasticsearchContainer elasticsearchContainer = new ElasticsearchContainer(
- "docker.elastic.co/elasticsearch/elasticsearch:8.16.1")
+ "docker.elastic.co/elasticsearch/elasticsearch:9.2.0")
.withEnv("xpack.security.enabled", "false");
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ElasticsearchRestClientAutoConfiguration.class,
- ElasticsearchVectorStoreAutoConfiguration.class, RestClientAutoConfiguration.class,
- SpringAiRetryAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class))
+ ElasticsearchVectorStoreAutoConfiguration.class, SpringAiRetryAutoConfiguration.class,
+ OpenAiEmbeddingAutoConfiguration.class))
.withUserConfiguration(Config.class)
.withPropertyValues("spring.elasticsearch.uris=" + elasticsearchContainer.getHttpHostAddress(),
"spring.ai.vectorstore.elasticsearch.initializeSchema=true",
@@ -131,8 +130,8 @@ public void propertiesTest() {
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ElasticsearchRestClientAutoConfiguration.class,
- ElasticsearchVectorStoreAutoConfiguration.class, RestClientAutoConfiguration.class,
- SpringAiRetryAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class))
+ ElasticsearchVectorStoreAutoConfiguration.class, SpringAiRetryAutoConfiguration.class,
+ OpenAiEmbeddingAutoConfiguration.class))
.withPropertyValues("spring.elasticsearch.uris=" + elasticsearchContainer.getHttpHostAddress(),
"spring.ai.openai.api-key=" + System.getenv("OPENAI_API_KEY"),
"spring.ai.vectorstore.elasticsearch.initializeSchema=true",
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-gemfire/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-gemfire/pom.xml
index 35046e17c81..6339c0e92ef 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-gemfire/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-gemfire/pom.xml
@@ -83,7 +83,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -94,7 +94,7 @@
dev.gemfire
gemfire-testcontainers
- 2.3.0
+ ${gemfire.testcontainers.version}
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-gemfire/src/test/java/org/testcontainers/containers/FailureDetectingExternalResource.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-gemfire/src/test/java/org/testcontainers/containers/FailureDetectingExternalResource.java
new file mode 100644
index 00000000000..68c1cba9d1f
--- /dev/null
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-gemfire/src/test/java/org/testcontainers/containers/FailureDetectingExternalResource.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2023-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.testcontainers.containers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.MultipleFailureException;
+import org.junit.runners.model.Statement;
+
+/**
+ * {@link TestRule} which is called before and after each test, and also is notified on
+ * success/failure.
+ *
+ * This mimics the behaviour of TestWatcher to some degree, but failures occurring in this
+ * rule do not contribute to the overall failure count (which can otherwise cause strange
+ * negative test success figures).
+ */
+public class FailureDetectingExternalResource implements TestRule {
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+
+ List errors = new ArrayList();
+
+ starting(description);
+
+ try {
+ base.evaluate();
+ succeeded(description);
+ }
+ catch (Throwable e) {
+ errors.add(e);
+ failed(e, description);
+ }
+ finally {
+ finished(description);
+ }
+
+ MultipleFailureException.assertEmpty(errors);
+ }
+ };
+ }
+
+ protected void starting(Description description) {
+
+ }
+
+ protected void succeeded(Description description) {
+ }
+
+ protected void failed(Throwable e, Description description) {
+ }
+
+ protected void finished(Description description) {
+ }
+
+}
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/pom.xml
index d773cc1773f..a4ba5918a58 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/pom.xml
@@ -49,6 +49,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
org.springframework.boot
spring-boot-configuration-processor
@@ -83,7 +87,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +97,7 @@
org.testcontainers
- mariadb
+ testcontainers-mariadb
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/src/main/java/org/springframework/ai/vectorstore/mariadb/autoconfigure/MariaDbStoreAutoConfiguration.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/src/main/java/org/springframework/ai/vectorstore/mariadb/autoconfigure/MariaDbStoreAutoConfiguration.java
index 0c9606646f5..33b3d01b2a0 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/src/main/java/org/springframework/ai/vectorstore/mariadb/autoconfigure/MariaDbStoreAutoConfiguration.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/src/main/java/org/springframework/ai/vectorstore/mariadb/autoconfigure/MariaDbStoreAutoConfiguration.java
@@ -31,8 +31,8 @@
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.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/src/test/java/org/springframework/ai/vectorstore/mariadb/autoconfigure/MariaDbStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/src/test/java/org/springframework/ai/vectorstore/mariadb/autoconfigure/MariaDbStoreAutoConfigurationIT.java
index 09fbfd6ad0b..b708eb559ac 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/src/test/java/org/springframework/ai/vectorstore/mariadb/autoconfigure/MariaDbStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mariadb/src/test/java/org/springframework/ai/vectorstore/mariadb/autoconfigure/MariaDbStoreAutoConfigurationIT.java
@@ -39,8 +39,8 @@
import org.springframework.ai.vectorstore.mariadb.MariaDBVectorStore;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-milvus/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-milvus/pom.xml
index a90f238a48f..bd394835d03 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-milvus/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-milvus/pom.xml
@@ -83,7 +83,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +93,7 @@
org.testcontainers
- milvus
+ testcontainers-milvus
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mongodb-atlas/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mongodb-atlas/pom.xml
index 6d283e019ca..deab09dde74 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mongodb-atlas/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mongodb-atlas/pom.xml
@@ -54,6 +54,16 @@
spring-boot-configuration-processor
true
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+ true
+
org.springframework.boot
spring-boot-autoconfigure-processor
@@ -83,7 +93,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +103,7 @@
org.testcontainers
- mongodb
+ testcontainers-mongodb
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mongodb-atlas/src/test/java/org/springframework/ai/vectorstore/mongodb/autoconfigure/MongoDBAtlasVectorStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mongodb-atlas/src/test/java/org/springframework/ai/vectorstore/mongodb/autoconfigure/MongoDBAtlasVectorStoreAutoConfigurationIT.java
index afd2723b452..7061a617f26 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mongodb-atlas/src/test/java/org/springframework/ai/vectorstore/mongodb/autoconfigure/MongoDBAtlasVectorStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-mongodb-atlas/src/test/java/org/springframework/ai/vectorstore/mongodb/autoconfigure/MongoDBAtlasVectorStoreAutoConfigurationIT.java
@@ -38,9 +38,9 @@
import org.springframework.ai.vectorstore.mongodb.atlas.MongoDBAtlasVectorStore;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
-import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
-import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
+import org.springframework.boot.data.mongodb.autoconfigure.DataMongoAutoConfiguration;
+import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration;
+import org.springframework.boot.restclient.autoconfigure.RestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -63,7 +63,7 @@ class MongoDBAtlasVectorStoreAutoConfigurationIT {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(Config.class)
- .withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
+ .withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, DataMongoAutoConfiguration.class,
MongoDBAtlasVectorStoreAutoConfiguration.class, RestClientAutoConfiguration.class,
SpringAiRetryAutoConfiguration.class, OpenAiEmbeddingAutoConfiguration.class))
.withPropertyValues("spring.data.mongodb.database=springaisample",
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/pom.xml
index 94654167324..9600acdf5c5 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/pom.xml
@@ -49,6 +49,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-neo4j
+
org.springframework.boot
spring-boot-configuration-processor
@@ -83,7 +87,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +97,7 @@
org.testcontainers
- neo4j
+ testcontainers-neo4j
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/src/main/java/org/springframework/ai/vectorstore/neo4j/autoconfigure/Neo4jVectorStoreAutoConfiguration.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/src/main/java/org/springframework/ai/vectorstore/neo4j/autoconfigure/Neo4jVectorStoreAutoConfiguration.java
index c7b5c8db926..c416ad8cad5 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/src/main/java/org/springframework/ai/vectorstore/neo4j/autoconfigure/Neo4jVectorStoreAutoConfiguration.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/src/main/java/org/springframework/ai/vectorstore/neo4j/autoconfigure/Neo4jVectorStoreAutoConfiguration.java
@@ -30,8 +30,8 @@
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.neo4j.Neo4jAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.neo4j.autoconfigure.Neo4jAutoConfiguration;
import org.springframework.context.annotation.Bean;
/**
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/src/test/java/org/springframework/ai/vectorstore/neo4j/autoconfigure/Neo4jVectorStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/src/test/java/org/springframework/ai/vectorstore/neo4j/autoconfigure/Neo4jVectorStoreAutoConfigurationIT.java
index fd9077d6c73..47ff53d9987 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/src/test/java/org/springframework/ai/vectorstore/neo4j/autoconfigure/Neo4jVectorStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-neo4j/src/test/java/org/springframework/ai/vectorstore/neo4j/autoconfigure/Neo4jVectorStoreAutoConfigurationIT.java
@@ -37,7 +37,7 @@
import org.springframework.ai.vectorstore.neo4j.Neo4jVectorStore;
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
+import org.springframework.boot.neo4j.autoconfigure.Neo4jAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/pom.xml
index 36f569fb9c4..354b02a35a3 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/pom.xml
@@ -96,23 +96,23 @@
org.testcontainers
- testcontainers
+ testcontainers-junit-jupiter
test
- org.testcontainers
- junit-jupiter
+ org.awaitility
+ awaitility
test
- org.awaitility
- awaitility
+ org.testcontainers
+ testcontainers-localstack
test
org.opensearch
opensearch-testcontainers
- 2.0.1
+ 4.0.0
test
@@ -129,7 +129,7 @@
org.testcontainers
- localstack
+ testcontainers-localstack
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/src/test/java/org/springframework/ai/vectorstore/opensearch/autoconfigure/OpenSearchVectorStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/src/test/java/org/springframework/ai/vectorstore/opensearch/autoconfigure/OpenSearchVectorStoreAutoConfigurationIT.java
index afe7e178957..92fabb4c83e 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/src/test/java/org/springframework/ai/vectorstore/opensearch/autoconfigure/OpenSearchVectorStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/src/test/java/org/springframework/ai/vectorstore/opensearch/autoconfigure/OpenSearchVectorStoreAutoConfigurationIT.java
@@ -26,7 +26,7 @@
import org.junit.jupiter.api.Test;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.Transport;
-import org.opensearch.testcontainers.OpensearchContainer;
+import org.opensearch.testcontainers.OpenSearchContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
@@ -60,7 +60,7 @@
class OpenSearchVectorStoreAutoConfigurationIT {
@Container
- private static final OpensearchContainer> opensearchContainer = new OpensearchContainer<>(
+ private static final OpenSearchContainer> opensearchContainer = new OpenSearchContainer<>(
DockerImageName.parse("opensearchproject/opensearch:2.13.0"));
private static final String DOCUMENT_INDEX = "auto-spring-ai-document-index";
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/src/test/java/org/springframework/ai/vectorstore/opensearch/autoconfigure/OpenSearchVectorStoreNonAwsFallbackIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/src/test/java/org/springframework/ai/vectorstore/opensearch/autoconfigure/OpenSearchVectorStoreNonAwsFallbackIT.java
index ea51b6d0fd4..e59e083db1e 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/src/test/java/org/springframework/ai/vectorstore/opensearch/autoconfigure/OpenSearchVectorStoreNonAwsFallbackIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-opensearch/src/test/java/org/springframework/ai/vectorstore/opensearch/autoconfigure/OpenSearchVectorStoreNonAwsFallbackIT.java
@@ -22,7 +22,7 @@
import java.util.Map;
import org.junit.jupiter.api.Test;
-import org.opensearch.testcontainers.OpensearchContainer;
+import org.opensearch.testcontainers.OpenSearchContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
@@ -44,7 +44,7 @@
class OpenSearchVectorStoreNonAwsFallbackIT {
@Container
- private static final OpensearchContainer> opensearchContainer = new OpensearchContainer<>(
+ private static final OpenSearchContainer> opensearchContainer = new OpenSearchContainer<>(
DockerImageName.parse("opensearchproject/opensearch:2.13.0"));
private static final String DOCUMENT_INDEX = "nonaws-spring-ai-document-index";
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/pom.xml
index 66c6202bd82..f978aadcbb0 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/pom.xml
@@ -49,6 +49,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
org.springframework.boot
spring-boot-configuration-processor
@@ -83,7 +87,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +97,7 @@
org.testcontainers
- oracle-free
+ testcontainers-oracle-free
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/src/main/java/org/springframework/ai/vectorstore/oracle/autoconfigure/OracleVectorStoreAutoConfiguration.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/src/main/java/org/springframework/ai/vectorstore/oracle/autoconfigure/OracleVectorStoreAutoConfiguration.java
index eb31a4dda94..2dacb76b2a9 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/src/main/java/org/springframework/ai/vectorstore/oracle/autoconfigure/OracleVectorStoreAutoConfiguration.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/src/main/java/org/springframework/ai/vectorstore/oracle/autoconfigure/OracleVectorStoreAutoConfiguration.java
@@ -31,8 +31,8 @@
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.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/src/test/java/org/springframework/ai/vectorstore/oracle/autoconfigure/OracleVectorStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/src/test/java/org/springframework/ai/vectorstore/oracle/autoconfigure/OracleVectorStoreAutoConfigurationIT.java
index 1e1261389bd..61ca7179ae8 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/src/test/java/org/springframework/ai/vectorstore/oracle/autoconfigure/OracleVectorStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-oracle/src/test/java/org/springframework/ai/vectorstore/oracle/autoconfigure/OracleVectorStoreAutoConfigurationIT.java
@@ -38,8 +38,8 @@
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import org.springframework.ai.vectorstore.oracle.OracleVectorStore;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/pom.xml
index 9bc06e4b948..4ea2663a80b 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/pom.xml
@@ -49,6 +49,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
org.springframework.boot
spring-boot-configuration-processor
@@ -67,23 +71,23 @@
test
- org.springframework.boot
- spring-boot-starter-test
+ org.testcontainers
+ testcontainers-junit-jupiter
test
- org.springframework.boot
- spring-boot-testcontainers
+ org.awaitility
+ awaitility
test
- org.testcontainers
- testcontainers
+ org.postgresql
+ postgresql
test
org.testcontainers
- junit-jupiter
+ testcontainers-postgresql
test
@@ -97,10 +101,5 @@
${project.parent.version}
test
-
- org.testcontainers
- postgresql
- test
-
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/src/main/java/org/springframework/ai/vectorstore/pgvector/autoconfigure/PgVectorStoreAutoConfiguration.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/src/main/java/org/springframework/ai/vectorstore/pgvector/autoconfigure/PgVectorStoreAutoConfiguration.java
index 839d88a37e9..f7f5f297d75 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/src/main/java/org/springframework/ai/vectorstore/pgvector/autoconfigure/PgVectorStoreAutoConfiguration.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/src/main/java/org/springframework/ai/vectorstore/pgvector/autoconfigure/PgVectorStoreAutoConfiguration.java
@@ -31,8 +31,8 @@
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.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/src/test/java/org/springframework/ai/vectorstore/pgvector/autoconfigure/PgVectorStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/src/test/java/org/springframework/ai/vectorstore/pgvector/autoconfigure/PgVectorStoreAutoConfigurationIT.java
index 3958c109cdb..efca91bf3f7 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/src/test/java/org/springframework/ai/vectorstore/pgvector/autoconfigure/PgVectorStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pgvector/src/test/java/org/springframework/ai/vectorstore/pgvector/autoconfigure/PgVectorStoreAutoConfigurationIT.java
@@ -39,8 +39,8 @@
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import org.springframework.ai.vectorstore.pgvector.PgVectorStore;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pinecone/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pinecone/pom.xml
index d37ab34decd..227a86fcc4d 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pinecone/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-pinecone/pom.xml
@@ -83,7 +83,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-qdrant/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-qdrant/pom.xml
index 4123208f072..089309205c2 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-qdrant/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-qdrant/pom.xml
@@ -88,17 +88,17 @@
org.testcontainers
- testcontainers
+ testcontainers-qdrant
test
- org.testcontainers
- qdrant
+ org.awaitility
+ awaitility
test
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/pom.xml
index a01969180e1..6b57660413e 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/pom.xml
@@ -49,6 +49,11 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+ true
+
org.springframework.boot
spring-boot-configuration-processor
@@ -56,7 +61,7 @@
org.springframework.boot
- spring-boot-autoconfigure-processor
+ spring-boot-data-redis
true
@@ -83,7 +88,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/src/main/java/org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreAutoConfiguration.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/src/main/java/org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreAutoConfiguration.java
index abb5b629bb4..d63719c13c8 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/src/main/java/org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreAutoConfiguration.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/src/main/java/org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreAutoConfiguration.java
@@ -34,8 +34,8 @@
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.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
@@ -47,7 +47,7 @@
* @author Soby Chacko
* @author Jihoon Kim
*/
-@AutoConfiguration(after = RedisAutoConfiguration.class)
+@AutoConfiguration(after = DataRedisAutoConfiguration.class)
@ConditionalOnClass({ JedisPooled.class, JedisConnectionFactory.class, RedisVectorStore.class, EmbeddingModel.class })
@ConditionalOnBean(JedisConnectionFactory.class)
@EnableConfigurationProperties(RedisVectorStoreProperties.class)
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/src/test/java/org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreAutoConfigurationIT.java b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/src/test/java/org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreAutoConfigurationIT.java
index 40d3bce6e93..9e19525a3db 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/src/test/java/org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreAutoConfigurationIT.java
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-redis/src/test/java/org/springframework/ai/vectorstore/redis/autoconfigure/RedisVectorStoreAutoConfigurationIT.java
@@ -36,7 +36,7 @@
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
import org.springframework.ai.vectorstore.redis.RedisVectorStore;
import org.springframework.boot.autoconfigure.AutoConfigurations;
-import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -58,12 +58,14 @@ class RedisVectorStoreAutoConfigurationIT {
RedisStackContainer.DEFAULT_IMAGE_NAME.withTag(RedisStackContainer.DEFAULT_TAG));
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
- .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class, RedisVectorStoreAutoConfiguration.class))
+ .withConfiguration(
+ AutoConfigurations.of(DataRedisAutoConfiguration.class, RedisVectorStoreAutoConfiguration.class))
.withUserConfiguration(Config.class)
.withPropertyValues("spring.data.redis.url=" + redisContainer.getRedisURI())
.withPropertyValues("spring.ai.vectorstore.redis.initialize-schema=true")
.withPropertyValues("spring.ai.vectorstore.redis.index=myIdx")
- .withPropertyValues("spring.ai.vectorstore.redis.prefix=doc:");
+ .withPropertyValues("spring.ai.vectorstore.redis.prefix=doc:")
+ .withPropertyValues("spring.data.redis.client-type=jedis");
List documents = List.of(
new Document(ResourceUtils.getText("classpath:/test/data/spring.ai.txt"), Map.of("spring", "great")),
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-typesense/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-typesense/pom.xml
index 31b72e1f345..a78f195e0c0 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-typesense/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-typesense/pom.xml
@@ -83,7 +83,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +93,7 @@
org.testcontainers
- typesense
+ testcontainers-typesense
test
diff --git a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-weaviate/pom.xml b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-weaviate/pom.xml
index ef5b555402f..62810f13e96 100644
--- a/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-weaviate/pom.xml
+++ b/auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-weaviate/pom.xml
@@ -83,7 +83,7 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
@@ -93,7 +93,7 @@
org.testcontainers
- weaviate
+ testcontainers-weaviate
test
diff --git a/document-readers/pdf-reader/pom.xml b/document-readers/pdf-reader/pom.xml
index 927423f74e0..ad84d10ff84 100644
--- a/document-readers/pdf-reader/pom.xml
+++ b/document-readers/pdf-reader/pom.xml
@@ -80,10 +80,10 @@
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
-
\ No newline at end of file
+
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-cassandra/pom.xml b/memory/repository/spring-ai-model-chat-memory-repository-cassandra/pom.xml
index 99a26be2e85..e3b3434a78f 100644
--- a/memory/repository/spring-ai-model-chat-memory-repository-cassandra/pom.xml
+++ b/memory/repository/spring-ai-model-chat-memory-repository-cassandra/pom.xml
@@ -71,13 +71,13 @@
org.testcontainers
- cassandra
+ testcontainers-cassandra
test
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-cassandra/src/test/java/org/springframework/ai/chat/memory/repository/cassandra/CassandraChatMemoryRepositoryIT.java b/memory/repository/spring-ai-model-chat-memory-repository-cassandra/src/test/java/org/springframework/ai/chat/memory/repository/cassandra/CassandraChatMemoryRepositoryIT.java
index 455aedcd094..217d23b18c0 100644
--- a/memory/repository/spring-ai-model-chat-memory-repository-cassandra/src/test/java/org/springframework/ai/chat/memory/repository/cassandra/CassandraChatMemoryRepositoryIT.java
+++ b/memory/repository/spring-ai-model-chat-memory-repository-cassandra/src/test/java/org/springframework/ai/chat/memory/repository/cassandra/CassandraChatMemoryRepositoryIT.java
@@ -38,8 +38,6 @@
import org.springframework.ai.chat.messages.MessageType;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.boot.SpringBootConfiguration;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
@@ -232,7 +230,6 @@ void clear_shouldDeleteMessages() {
}
@SpringBootConfiguration
- @EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
public static class TestApplication {
@Bean
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/pom.xml b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/pom.xml
index d24854cb3f7..420d77b50fe 100644
--- a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/pom.xml
+++ b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/pom.xml
@@ -127,37 +127,36 @@
org.testcontainers
testcontainers-oracle-free
- 2.0.1
test
org.testcontainers
- postgresql
+ testcontainers-postgresql
test
org.testcontainers
- mariadb
+ testcontainers-mariadb
test
org.testcontainers
- mysql
+ testcontainers-mysql
test
org.testcontainers
- mssqlserver
+ testcontainers-mssqlserver
test
org.testcontainers
- junit-jupiter
+ testcontainers-junit-jupiter
test
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/AbstractJdbcChatMemoryRepositoryIT.java b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/AbstractJdbcChatMemoryRepositoryIT.java
index 507aee30743..27ac1f2c70e 100644
--- a/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/AbstractJdbcChatMemoryRepositoryIT.java
+++ b/memory/repository/spring-ai-model-chat-memory-repository-jdbc/src/test/java/org/springframework/ai/chat/memory/repository/jdbc/AbstractJdbcChatMemoryRepositoryIT.java
@@ -34,8 +34,8 @@
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
+import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-neo4j/pom.xml b/memory/repository/spring-ai-model-chat-memory-repository-neo4j/pom.xml
index 050d9438840..133df80df78 100644
--- a/memory/repository/spring-ai-model-chat-memory-repository-neo4j/pom.xml
+++ b/memory/repository/spring-ai-model-chat-memory-repository-neo4j/pom.xml
@@ -81,17 +81,17 @@
neo4j-java-driver
-
- org.testcontainers
- neo4j
- test
-
+
+ org.testcontainers
+ testcontainers-neo4j
+ test
+
-
- org.testcontainers
- junit-jupiter
- test
-
+
+ org.testcontainers
+ testcontainers-junit-jupiter
+ test
+
diff --git a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java
index 40010e11ad9..f7e0567fd03 100644
--- a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java
+++ b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicChatModel.java
@@ -78,11 +78,12 @@
import org.springframework.ai.support.UsageCalculator;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.ai.util.json.JsonParser;
+import org.springframework.core.retry.RetryException;
+import org.springframework.core.retry.RetryTemplate;
+import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
-import org.springframework.retry.support.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
-import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
/**
@@ -193,8 +194,19 @@ public ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespons
this.observationRegistry)
.observe(() -> {
- ResponseEntity completionEntity = this.retryTemplate.execute(
- ctx -> this.anthropicApi.chatCompletionEntity(request, this.getAdditionalHttpHeaders(prompt)));
+ ResponseEntity completionEntity = null;
+ try {
+ completionEntity = this.retryTemplate.execute(() -> this.anthropicApi.chatCompletionEntity(request,
+ this.getAdditionalHttpHeaders(prompt)));
+ }
+ catch (RetryException e) {
+ if (e.getCause() instanceof RuntimeException r) {
+ throw r;
+ }
+ else {
+ throw new RuntimeException(e.getCause());
+ }
+ }
AnthropicApi.ChatCompletionResponse completionResponse = completionEntity.getBody();
AnthropicApi.Usage usage = completionResponse.usage();
@@ -523,14 +535,15 @@ else if (mimeType.contains("pdf")) {
+ ". Supported types are: images (image/*) and PDF documents (application/pdf)");
}
- private MultiValueMap getAdditionalHttpHeaders(Prompt prompt) {
+ private HttpHeaders getAdditionalHttpHeaders(Prompt prompt) {
Map headers = new HashMap<>(this.defaultOptions.getHttpHeaders());
if (prompt.getOptions() != null && prompt.getOptions() instanceof AnthropicChatOptions chatOptions) {
headers.putAll(chatOptions.getHttpHeaders());
}
- return CollectionUtils.toMultiValueMap(
- headers.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> List.of(e.getValue()))));
+ HttpHeaders httpHeaders = new HttpHeaders();
+ headers.forEach(httpHeaders::add);
+ return httpHeaders;
}
Prompt buildRequestPrompt(Prompt prompt) {
diff --git a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java
index 497d43acc4a..e18c4d38801 100644
--- a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java
+++ b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java
@@ -48,8 +48,6 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
@@ -148,6 +146,20 @@ private AnthropicApi(String baseUrl, String completionsPath, ApiKey anthropicApi
.build();
}
+ /**
+ * Create a new client api.
+ * @param completionsPath path to append to the base URL.
+ * @param restClient RestClient instance.
+ * @param webClient WebClient instance.
+ * @param apiKey Anthropic api Key.
+ */
+ public AnthropicApi(String completionsPath, RestClient restClient, WebClient webClient, ApiKey apiKey) {
+ this.completionsPath = completionsPath;
+ this.restClient = restClient;
+ this.webClient = webClient;
+ this.apiKey = apiKey;
+ }
+
/**
* Creates a model response for the given chat conversation.
* @param chatRequest The chat completion request.
@@ -155,7 +167,7 @@ private AnthropicApi(String baseUrl, String completionsPath, ApiKey anthropicApi
* status code and headers.
*/
public ResponseEntity chatCompletionEntity(ChatCompletionRequest chatRequest) {
- return chatCompletionEntity(chatRequest, new LinkedMultiValueMap<>());
+ return chatCompletionEntity(chatRequest, new HttpHeaders());
}
/**
@@ -166,7 +178,7 @@ public ResponseEntity chatCompletionEntity(ChatCompletio
* status code and headers.
*/
public ResponseEntity chatCompletionEntity(ChatCompletionRequest chatRequest,
- MultiValueMap additionalHttpHeader) {
+ HttpHeaders additionalHttpHeader) {
Assert.notNull(chatRequest, "The request body can not be null.");
Assert.isTrue(!chatRequest.stream(), "Request must set the stream property to false.");
@@ -192,7 +204,7 @@ public ResponseEntity chatCompletionEntity(ChatCompletio
* @return Returns a {@link Flux} stream from chat completion chunks.
*/
public Flux chatCompletionStream(ChatCompletionRequest chatRequest) {
- return chatCompletionStream(chatRequest, new LinkedMultiValueMap<>());
+ return chatCompletionStream(chatRequest, new HttpHeaders());
}
/**
@@ -203,7 +215,7 @@ public Flux chatCompletionStream(ChatCompletionRequest c
* @return Returns a {@link Flux} stream from chat completion chunks.
*/
public Flux chatCompletionStream(ChatCompletionRequest chatRequest,
- MultiValueMap additionalHttpHeader) {
+ HttpHeaders additionalHttpHeader) {
Assert.notNull(chatRequest, "The request body can not be null.");
Assert.isTrue(chatRequest.stream(), "Request must set the stream property to true.");
@@ -256,7 +268,7 @@ public Flux chatCompletionStream(ChatCompletionRequest c
}
private void addDefaultHeadersIfMissing(HttpHeaders headers) {
- if (!headers.containsKey(HEADER_X_API_KEY)) {
+ if (!headers.containsHeader(HEADER_X_API_KEY)) {
String apiKeyValue = this.apiKey.getValue();
if (StringUtils.hasText(apiKeyValue)) {
headers.add(HEADER_X_API_KEY, apiKeyValue);
diff --git a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatModelObservationIT.java b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatModelObservationIT.java
index 910f572d208..382dbe6f64f 100644
--- a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatModelObservationIT.java
+++ b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatModelObservationIT.java
@@ -40,7 +40,7 @@
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import static org.assertj.core.api.Assertions.assertThat;
@@ -171,7 +171,7 @@ public AnthropicApi anthropicApi() {
public AnthropicChatModel anthropicChatModel(AnthropicApi anthropicApi,
TestObservationRegistry observationRegistry) {
return new AnthropicChatModel(anthropicApi, AnthropicChatOptions.builder().build(),
- ToolCallingManager.builder().build(), RetryTemplate.defaultInstance(), observationRegistry);
+ ToolCallingManager.builder().build(), new RetryTemplate(), observationRegistry);
}
}
diff --git a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/api/AnthropicApiBuilderTests.java b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/api/AnthropicApiBuilderTests.java
index 1f42a35a67e..6b2a1caf8d1 100644
--- a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/api/AnthropicApiBuilderTests.java
+++ b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/api/AnthropicApiBuilderTests.java
@@ -37,8 +37,6 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
@@ -304,7 +302,7 @@ void dynamicApiKeyRestClientWithAdditionalApiKeyHeader() throws InterruptedExcep
.temperature(0.8)
.messages(List.of(chatCompletionMessage))
.build();
- MultiValueMap additionalHeaders = new LinkedMultiValueMap<>();
+ var additionalHeaders = new HttpHeaders();
additionalHeaders.add("x-api-key", "additional-key");
ResponseEntity response = api.chatCompletionEntity(request,
additionalHeaders);
@@ -403,7 +401,7 @@ void dynamicApiKeyWebClientWithAdditionalApiKey() throws InterruptedException {
.messages(List.of(chatCompletionMessage))
.stream(true)
.build();
- MultiValueMap additionalHeaders = new LinkedMultiValueMap<>();
+ var additionalHeaders = new HttpHeaders();
additionalHeaders.add("x-api-key", "additional-key");
api.chatCompletionStream(request, additionalHeaders).collectList().block();
diff --git a/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatModel.java b/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatModel.java
index fba44ffd4ce..c89a1c0c812 100644
--- a/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatModel.java
+++ b/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/DeepSeekChatModel.java
@@ -66,8 +66,9 @@
import org.springframework.ai.retry.RetryUtils;
import org.springframework.ai.support.UsageCalculator;
import org.springframework.ai.tool.definition.ToolDefinition;
+import org.springframework.core.retry.RetryException;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.http.ResponseEntity;
-import org.springframework.retry.support.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@@ -165,8 +166,18 @@ public ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespons
this.observationRegistry)
.observe(() -> {
- ResponseEntity completionEntity = this.retryTemplate
- .execute(ctx -> this.deepSeekApi.chatCompletionEntity(request));
+ ResponseEntity completionEntity = null;
+ try {
+ completionEntity = this.retryTemplate.execute(() -> this.deepSeekApi.chatCompletionEntity(request));
+ }
+ catch (RetryException e) {
+ if (e.getCause() instanceof RuntimeException r) {
+ throw r;
+ }
+ else {
+ throw new RuntimeException(e.getCause());
+ }
+ }
var chatCompletion = completionEntity.getBody();
diff --git a/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/api/DeepSeekApi.java b/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/api/DeepSeekApi.java
index 13415829854..13667f0e3d5 100644
--- a/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/api/DeepSeekApi.java
+++ b/models/spring-ai-deepseek/src/main/java/org/springframework/ai/deepseek/api/DeepSeekApi.java
@@ -41,8 +41,6 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
@@ -67,7 +65,7 @@ public class DeepSeekApi {
private final WebClient webClient;
- private DeepSeekStreamFunctionCallingHelper chunkMerger = new DeepSeekStreamFunctionCallingHelper();
+ private final DeepSeekStreamFunctionCallingHelper chunkMerger = new DeepSeekStreamFunctionCallingHelper();
/**
* Create a new chat completion api.
@@ -80,7 +78,7 @@ public class DeepSeekApi {
* @param webClientBuilder WebClient builder.
* @param responseErrorHandler Response error handler.
*/
- public DeepSeekApi(String baseUrl, ApiKey apiKey, MultiValueMap headers, String completionsPath,
+ public DeepSeekApi(String baseUrl, ApiKey apiKey, HttpHeaders headers, String completionsPath,
String betaPrefixPath, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder,
ResponseErrorHandler responseErrorHandler) {
@@ -90,21 +88,39 @@ public DeepSeekApi(String baseUrl, ApiKey apiKey, MultiValueMap
this.completionsPath = completionsPath;
this.betaPrefixPath = betaPrefixPath;
- // @formatter:off
+
Consumer finalHeaders = h -> {
h.setBearerAuth(apiKey.getValue());
h.setContentType(MediaType.APPLICATION_JSON);
- h.addAll(headers);
+ h.addAll(HttpHeaders.readOnlyHttpHeaders(headers));
};
this.restClient = restClientBuilder.baseUrl(baseUrl)
.defaultHeaders(finalHeaders)
.defaultStatusHandler(responseErrorHandler)
.build();
- this.webClient = webClientBuilder
- .baseUrl(baseUrl)
- .defaultHeaders(finalHeaders)
- .build(); // @formatter:on
+ this.webClient = webClientBuilder.baseUrl(baseUrl).defaultHeaders(finalHeaders).build();
+
+ }
+
+ /**
+ * Create a new chat completion api.
+ * @param completionsPath the path to the chat completions endpoint.
+ * @param betaPrefixPath the prefix path to the beta feature endpoint.
+ * @param restClient RestClient instance.
+ * @param webClient WebClient instance.
+ */
+ public DeepSeekApi(String completionsPath, String betaPrefixPath, RestClient restClient, WebClient webClient) {
+
+ Assert.hasText(completionsPath, "Completions Path must not be null");
+ Assert.hasText(betaPrefixPath, "Beta feature path must not be null");
+ Assert.notNull(restClient, "RestClient must not be null");
+ Assert.notNull(webClient, "WebClient must not be null");
+
+ this.completionsPath = completionsPath;
+ this.betaPrefixPath = betaPrefixPath;
+ this.restClient = restClient;
+ this.webClient = webClient;
}
/**
@@ -132,7 +148,7 @@ public ResponseEntity chatCompletionEntity(ChatCompletionRequest
* @return Returns a {@link Flux} stream from chat completion chunks.
*/
public Flux chatCompletionStream(ChatCompletionRequest chatRequest) {
- return chatCompletionStream(chatRequest, new LinkedMultiValueMap<>());
+ return chatCompletionStream(chatRequest, new HttpHeaders());
}
/**
@@ -144,7 +160,7 @@ public Flux chatCompletionStream(ChatCompletionRequest chat
* @return Returns a {@link Flux} stream from chat completion chunks.
*/
public Flux chatCompletionStream(ChatCompletionRequest chatRequest,
- MultiValueMap additionalHttpHeader) {
+ HttpHeaders additionalHttpHeader) {
Assert.notNull(chatRequest, "The request body can not be null.");
Assert.isTrue(chatRequest.stream(), "Request must set the stream property to true.");
@@ -153,7 +169,7 @@ public Flux chatCompletionStream(ChatCompletionRequest chat
return this.webClient.post()
.uri(this.getEndpoint(chatRequest))
- .headers(headers -> headers.addAll(additionalHttpHeader))
+ .headers(headers -> headers.addAll(HttpHeaders.readOnlyHttpHeaders(additionalHttpHeader)))
.body(Mono.just(chatRequest), ChatCompletionRequest.class)
.retrieve()
.bodyToFlux(String.class)
@@ -911,7 +927,7 @@ public static final class Builder {
private ApiKey apiKey;
- private MultiValueMap headers = new LinkedMultiValueMap<>();
+ private HttpHeaders headers = new HttpHeaders();
private String completionsPath = org.springframework.ai.deepseek.api.common.DeepSeekConstants.DEFAULT_COMPLETIONS_PATH;
@@ -941,7 +957,7 @@ public Builder apiKey(String simpleApiKey) {
return this;
}
- public Builder headers(MultiValueMap headers) {
+ public Builder headers(HttpHeaders headers) {
Assert.notNull(headers, "headers cannot be null");
this.headers = headers;
return this;
diff --git a/models/spring-ai-deepseek/src/test/java/org/springframework/ai/deepseek/DeepSeekRetryTests.java b/models/spring-ai-deepseek/src/test/java/org/springframework/ai/deepseek/DeepSeekRetryTests.java
index 35f24eaadeb..511ee734806 100644
--- a/models/spring-ai-deepseek/src/test/java/org/springframework/ai/deepseek/DeepSeekRetryTests.java
+++ b/models/spring-ai-deepseek/src/test/java/org/springframework/ai/deepseek/DeepSeekRetryTests.java
@@ -34,11 +34,11 @@
import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionRequest;
import org.springframework.ai.retry.RetryUtils;
import org.springframework.ai.retry.TransientAiException;
+import org.springframework.core.retry.RetryListener;
+import org.springframework.core.retry.RetryPolicy;
+import org.springframework.core.retry.RetryTemplate;
+import org.springframework.core.retry.Retryable;
import org.springframework.http.ResponseEntity;
-import org.springframework.retry.RetryCallback;
-import org.springframework.retry.RetryContext;
-import org.springframework.retry.RetryListener;
-import org.springframework.retry.support.RetryTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -62,7 +62,7 @@ public class DeepSeekRetryTests {
public void beforeEach() {
RetryTemplate retryTemplate = RetryUtils.SHORT_RETRY_TEMPLATE;
this.retryListener = new TestRetryListener();
- retryTemplate.registerListener(this.retryListener);
+ retryTemplate.setRetryListener(this.retryListener);
this.chatModel = DeepSeekChatModel.builder()
.deepSeekApi(this.deepSeekApi)
@@ -88,7 +88,7 @@ public void deepSeekChatTransientError() {
assertThat(result).isNotNull();
assertThat(result.getResult().getOutput().getText()).isSameAs("Response");
- assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(2);
+ assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(1);
assertThat(this.retryListener.onErrorRetryCount).isEqualTo(2);
}
@@ -116,7 +116,7 @@ public void deepSeekChatStreamTransientError() {
assertThat(result).isNotNull();
assertThat(result.getResult().getOutput().getText()).isSameAs("Response");
- assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(2);
+ assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(1);
assertThat(this.retryListener.onErrorRetryCount).isEqualTo(2);
}
@@ -134,14 +134,15 @@ private static class TestRetryListener implements RetryListener {
int onSuccessRetryCount = 0;
@Override
- public void onSuccess(RetryContext context, RetryCallback callback, T result) {
- this.onSuccessRetryCount = context.getRetryCount();
+ public void beforeRetry(final RetryPolicy retryPolicy, final Retryable> retryable) {
+ // Count each retry attempt
+ this.onErrorRetryCount++;
}
@Override
- public void onError(RetryContext context, RetryCallback callback,
- Throwable throwable) {
- this.onErrorRetryCount = context.getRetryCount();
+ public void onRetrySuccess(final RetryPolicy retryPolicy, final Retryable> retryable, final Object result) {
+ // Count successful retries - we increment when we succeed after a failure
+ this.onSuccessRetryCount++;
}
}
diff --git a/models/spring-ai-deepseek/src/test/java/org/springframework/ai/deepseek/chat/DeepSeekChatModelObservationIT.java b/models/spring-ai-deepseek/src/test/java/org/springframework/ai/deepseek/chat/DeepSeekChatModelObservationIT.java
index 00e8732dade..b2900e479cb 100644
--- a/models/spring-ai-deepseek/src/test/java/org/springframework/ai/deepseek/chat/DeepSeekChatModelObservationIT.java
+++ b/models/spring-ai-deepseek/src/test/java/org/springframework/ai/deepseek/chat/DeepSeekChatModelObservationIT.java
@@ -40,7 +40,7 @@
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.ai.chat.observation.ChatModelObservationDocumentation.HighCardinalityKeyNames;
@@ -172,7 +172,7 @@ public DeepSeekApi deepSeekApi() {
public DeepSeekChatModel deepSeekChatModel(DeepSeekApi deepSeekApi,
TestObservationRegistry observationRegistry) {
return new DeepSeekChatModel(deepSeekApi, DeepSeekChatOptions.builder().build(),
- ToolCallingManager.builder().build(), RetryTemplate.defaultInstance(), observationRegistry);
+ ToolCallingManager.builder().build(), new RetryTemplate(), observationRegistry);
}
}
diff --git a/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/ElevenLabsTextToSpeechModel.java b/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/ElevenLabsTextToSpeechModel.java
index 68ed07568a8..b8220e87065 100644
--- a/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/ElevenLabsTextToSpeechModel.java
+++ b/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/ElevenLabsTextToSpeechModel.java
@@ -29,7 +29,8 @@
import org.springframework.ai.audio.tts.TextToSpeechResponse;
import org.springframework.ai.elevenlabs.api.ElevenLabsApi;
import org.springframework.ai.retry.RetryUtils;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryException;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -73,15 +74,26 @@ public static Builder builder() {
public TextToSpeechResponse call(TextToSpeechPrompt prompt) {
RequestContext requestContext = prepareRequest(prompt);
- byte[] audioData = this.retryTemplate.execute(context -> {
- var response = this.elevenLabsApi.textToSpeech(requestContext.request, requestContext.voiceId,
- requestContext.queryParameters);
- if (response.getBody() == null) {
- logger.warn("No speech response returned for request: {}", requestContext.request);
- return new byte[0];
+ byte[] audioData = null;
+ try {
+ audioData = this.retryTemplate.execute(() -> {
+ var response = this.elevenLabsApi.textToSpeech(requestContext.request, requestContext.voiceId,
+ requestContext.queryParameters);
+ if (response.getBody() == null) {
+ logger.warn("No speech response returned for request: {}", requestContext.request);
+ return new byte[0];
+ }
+ return response.getBody();
+ });
+ }
+ catch (RetryException e) {
+ if (e.getCause() instanceof RuntimeException r) {
+ throw r;
+ }
+ else {
+ throw new RuntimeException(e.getCause());
}
- return response.getBody();
- });
+ }
return new TextToSpeechResponse(List.of(new Speech(audioData)));
}
@@ -90,9 +102,19 @@ public TextToSpeechResponse call(TextToSpeechPrompt prompt) {
public Flux stream(TextToSpeechPrompt prompt) {
RequestContext requestContext = prepareRequest(prompt);
- return this.retryTemplate.execute(context -> this.elevenLabsApi
- .textToSpeechStream(requestContext.request, requestContext.voiceId, requestContext.queryParameters)
- .map(entity -> new TextToSpeechResponse(List.of(new Speech(entity.getBody())))));
+ try {
+ return this.retryTemplate.execute(() -> this.elevenLabsApi
+ .textToSpeechStream(requestContext.request, requestContext.voiceId, requestContext.queryParameters)
+ .map(entity -> new TextToSpeechResponse(List.of(new Speech(entity.getBody())))));
+ }
+ catch (RetryException e) {
+ if (e.getCause() instanceof RuntimeException r) {
+ throw r;
+ }
+ else {
+ throw new RuntimeException(e.getCause());
+ }
+ }
}
private RequestContext prepareRequest(TextToSpeechPrompt prompt) {
diff --git a/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/api/ElevenLabsApi.java b/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/api/ElevenLabsApi.java
index 10ce0349070..2f20727e17c 100644
--- a/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/api/ElevenLabsApi.java
+++ b/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/api/ElevenLabsApi.java
@@ -33,7 +33,6 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
-import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
@@ -62,15 +61,14 @@ public final class ElevenLabsApi {
* @param webClientBuilder A builder for the Spring WebClient.
* @param responseErrorHandler A custom error handler for API responses.
*/
- private ElevenLabsApi(String baseUrl, ApiKey apiKey, MultiValueMap headers,
- RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder,
- ResponseErrorHandler responseErrorHandler) {
+ private ElevenLabsApi(String baseUrl, ApiKey apiKey, HttpHeaders headers, RestClient.Builder restClientBuilder,
+ WebClient.Builder webClientBuilder, ResponseErrorHandler responseErrorHandler) {
Consumer jsonContentHeaders = h -> {
if (!(apiKey instanceof NoopApiKey)) {
h.set("xi-api-key", apiKey.getValue());
}
- h.addAll(headers);
+ h.addAll(HttpHeaders.readOnlyHttpHeaders(headers));
h.setContentType(MediaType.APPLICATION_JSON);
};
@@ -82,6 +80,16 @@ private ElevenLabsApi(String baseUrl, ApiKey apiKey, MultiValueMap headers = new LinkedMultiValueMap<>();
+ private HttpHeaders headers = new HttpHeaders();
private RestClient.Builder restClientBuilder = RestClient.builder();
@@ -357,7 +365,7 @@ public Builder apiKey(String simpleApiKey) {
return this;
}
- public Builder headers(MultiValueMap headers) {
+ public Builder headers(HttpHeaders headers) {
Assert.notNull(headers, "headers cannot be null");
this.headers = headers;
return this;
diff --git a/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/api/ElevenLabsVoicesApi.java b/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/api/ElevenLabsVoicesApi.java
index 3f6f6377937..766191a8a73 100644
--- a/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/api/ElevenLabsVoicesApi.java
+++ b/models/spring-ai-elevenlabs/src/main/java/org/springframework/ai/elevenlabs/api/ElevenLabsVoicesApi.java
@@ -32,8 +32,6 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
@@ -56,13 +54,13 @@ public class ElevenLabsVoicesApi {
* @param restClientBuilder A builder for the Spring RestClient.
* @param responseErrorHandler A custom error handler for API responses.
*/
- public ElevenLabsVoicesApi(String baseUrl, ApiKey apiKey, MultiValueMap headers,
- RestClient.Builder restClientBuilder, ResponseErrorHandler responseErrorHandler) {
+ public ElevenLabsVoicesApi(String baseUrl, ApiKey apiKey, HttpHeaders headers, RestClient.Builder restClientBuilder,
+ ResponseErrorHandler responseErrorHandler) {
Consumer jsonContentHeaders = h -> {
if (!(apiKey instanceof NoopApiKey)) {
h.set("xi-api-key", apiKey.getValue());
}
- h.addAll(headers);
+ h.addAll(HttpHeaders.readOnlyHttpHeaders(headers));
h.setContentType(MediaType.APPLICATION_JSON);
};
@@ -73,6 +71,14 @@ public ElevenLabsVoicesApi(String baseUrl, ApiKey apiKey, MultiValueMap headers = new LinkedMultiValueMap<>();
+ private HttpHeaders headers = new HttpHeaders();
private RestClient.Builder restClientBuilder = RestClient.builder();
@@ -423,7 +429,7 @@ public Builder apiKey(String simpleApiKey) {
return this;
}
- public Builder headers(MultiValueMap headers) {
+ public Builder headers(HttpHeaders headers) {
Assert.notNull(headers, "headers cannot be null");
this.headers = headers;
return this;
diff --git a/models/spring-ai-google-genai-embedding/src/main/java/org/springframework/ai/google/genai/text/GoogleGenAiTextEmbeddingModel.java b/models/spring-ai-google-genai-embedding/src/main/java/org/springframework/ai/google/genai/text/GoogleGenAiTextEmbeddingModel.java
index 46c87cd6862..049720082bf 100644
--- a/models/spring-ai-google-genai-embedding/src/main/java/org/springframework/ai/google/genai/text/GoogleGenAiTextEmbeddingModel.java
+++ b/models/spring-ai-google-genai-embedding/src/main/java/org/springframework/ai/google/genai/text/GoogleGenAiTextEmbeddingModel.java
@@ -46,7 +46,8 @@
import org.springframework.ai.model.ModelOptionsUtils;
import org.springframework.ai.observation.conventions.AiProvider;
import org.springframework.ai.retry.RetryUtils;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryException;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -168,8 +169,19 @@ public EmbeddingResponse call(EmbeddingRequest request) {
}
// Call the embedding API with retry
- EmbedContentResponse embeddingResponse = this.retryTemplate
- .execute(context -> this.genAiClient.models.embedContent(modelName, validTexts, config));
+ EmbedContentResponse embeddingResponse = null;
+ try {
+ embeddingResponse = this.retryTemplate
+ .execute(() -> this.genAiClient.models.embedContent(modelName, validTexts, config));
+ }
+ catch (RetryException e) {
+ if (e.getCause() instanceof RuntimeException r) {
+ throw r;
+ }
+ else {
+ throw new RuntimeException(e.getCause());
+ }
+ }
// Process the response
// Note: We need to handle the case where some texts were filtered out
diff --git a/models/spring-ai-google-genai-embedding/src/test/java/org/springframework/ai/google/genai/text/GoogleGenAiTextEmbeddingRetryTests.java b/models/spring-ai-google-genai-embedding/src/test/java/org/springframework/ai/google/genai/text/GoogleGenAiTextEmbeddingRetryTests.java
index 4dc9fce14c5..6d2136aca1a 100644
--- a/models/spring-ai-google-genai-embedding/src/test/java/org/springframework/ai/google/genai/text/GoogleGenAiTextEmbeddingRetryTests.java
+++ b/models/spring-ai-google-genai-embedding/src/test/java/org/springframework/ai/google/genai/text/GoogleGenAiTextEmbeddingRetryTests.java
@@ -36,10 +36,10 @@
import org.springframework.ai.google.genai.GoogleGenAiEmbeddingConnectionDetails;
import org.springframework.ai.retry.RetryUtils;
import org.springframework.ai.retry.TransientAiException;
-import org.springframework.retry.RetryCallback;
-import org.springframework.retry.RetryContext;
-import org.springframework.retry.RetryListener;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryListener;
+import org.springframework.core.retry.RetryPolicy;
+import org.springframework.core.retry.RetryTemplate;
+import org.springframework.core.retry.Retryable;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
@@ -75,7 +75,7 @@ public class GoogleGenAiTextEmbeddingRetryTests {
public void setUp() throws Exception {
this.retryTemplate = RetryUtils.SHORT_RETRY_TEMPLATE;
this.retryListener = new TestRetryListener();
- this.retryTemplate.registerListener(this.retryListener);
+ this.retryTemplate.setRetryListener(this.retryListener);
// Create a mock Client and use reflection to set the models field
this.mockGenAiClient = mock(Client.class);
@@ -114,7 +114,7 @@ public void vertexAiEmbeddingTransientError() {
assertThat(result).isNotNull();
assertThat(result.getResults()).hasSize(1);
assertThat(result.getResults().get(0).getOutput()).isEqualTo(new float[] { 9.9f, 8.8f });
- assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(2);
+ assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(1);
assertThat(this.retryListener.onErrorRetryCount).isEqualTo(2);
verify(this.mockModels, times(3)).embedContent(anyString(), any(List.class), any(EmbedContentConfig.class));
@@ -143,14 +143,15 @@ private static class TestRetryListener implements RetryListener {
int onSuccessRetryCount = 0;
@Override
- public void onSuccess(RetryContext context, RetryCallback callback, T result) {
- this.onSuccessRetryCount = context.getRetryCount();
+ public void beforeRetry(final RetryPolicy retryPolicy, final Retryable> retryable) {
+ // Count each retry attempt
+ this.onErrorRetryCount++;
}
@Override
- public void onError(RetryContext context, RetryCallback callback,
- Throwable throwable) {
- this.onErrorRetryCount = context.getRetryCount();
+ public void onRetrySuccess(final RetryPolicy retryPolicy, final Retryable> retryable, final Object result) {
+ // Count successful retries - we increment when we succeed after a failure
+ this.onSuccessRetryCount++;
}
}
diff --git a/models/spring-ai-google-genai-embedding/src/test/java/org/springframework/ai/google/genai/text/TestGoogleGenAiTextEmbeddingModel.java b/models/spring-ai-google-genai-embedding/src/test/java/org/springframework/ai/google/genai/text/TestGoogleGenAiTextEmbeddingModel.java
index 44a06031afc..9836f63ec30 100644
--- a/models/spring-ai-google-genai-embedding/src/test/java/org/springframework/ai/google/genai/text/TestGoogleGenAiTextEmbeddingModel.java
+++ b/models/spring-ai-google-genai-embedding/src/test/java/org/springframework/ai/google/genai/text/TestGoogleGenAiTextEmbeddingModel.java
@@ -17,7 +17,7 @@
package org.springframework.ai.google.genai.text;
import org.springframework.ai.google.genai.GoogleGenAiEmbeddingConnectionDetails;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
/**
* Test implementation of GoogleGenAiTextEmbeddingModel that uses a mock connection for
diff --git a/models/spring-ai-google-genai/src/main/java/org/springframework/ai/google/genai/GoogleGenAiChatModel.java b/models/spring-ai-google-genai/src/main/java/org/springframework/ai/google/genai/GoogleGenAiChatModel.java
index 8e38008e859..70f5c1385dc 100644
--- a/models/spring-ai-google-genai/src/main/java/org/springframework/ai/google/genai/GoogleGenAiChatModel.java
+++ b/models/spring-ai-google-genai/src/main/java/org/springframework/ai/google/genai/GoogleGenAiChatModel.java
@@ -87,8 +87,9 @@
import org.springframework.ai.support.UsageCalculator;
import org.springframework.ai.tool.definition.ToolDefinition;
import org.springframework.beans.factory.DisposableBean;
+import org.springframework.core.retry.RetryException;
+import org.springframework.core.retry.RetryTemplate;
import org.springframework.lang.NonNull;
-import org.springframework.retry.support.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
@@ -404,30 +405,41 @@ private ChatResponse internalCall(Prompt prompt, ChatResponse previousChatRespon
ChatResponse response = ChatModelObservationDocumentation.CHAT_MODEL_OPERATION
.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
this.observationRegistry)
- .observe(() -> this.retryTemplate.execute(context -> {
-
- var geminiRequest = createGeminiRequest(prompt);
-
- GenerateContentResponse generateContentResponse = this.getContentResponse(geminiRequest);
+ .observe(() -> {
+ try {
+ return this.retryTemplate.execute(() -> {
+
+ var geminiRequest = createGeminiRequest(prompt);
+
+ GenerateContentResponse generateContentResponse = this.getContentResponse(geminiRequest);
+
+ List generations = generateContentResponse.candidates()
+ .orElse(List.of())
+ .stream()
+ .map(this::responseCandidateToGeneration)
+ .flatMap(List::stream)
+ .toList();
+
+ var usage = generateContentResponse.usageMetadata();
+ GoogleGenAiChatOptions options = (GoogleGenAiChatOptions) prompt.getOptions();
+ Usage currentUsage = (usage.isPresent()) ? getDefaultUsage(usage.get(), options)
+ : getDefaultUsage(null, options);
+ Usage cumulativeUsage = UsageCalculator.getCumulativeUsage(currentUsage, previousChatResponse);
+ ChatResponse chatResponse = new ChatResponse(generations,
+ toChatResponseMetadata(cumulativeUsage, generateContentResponse.modelVersion().get()));
+
+ observationContext.setResponse(chatResponse);
+ return chatResponse;
+ });
+ }
+ catch (RetryException e) {
+ if (e.getCause() instanceof RuntimeException r) {
+ throw r;
+ }
- List generations = generateContentResponse.candidates()
- .orElse(List.of())
- .stream()
- .map(this::responseCandidateToGeneration)
- .flatMap(List::stream)
- .toList();
-
- var usage = generateContentResponse.usageMetadata();
- GoogleGenAiChatOptions options = (GoogleGenAiChatOptions) prompt.getOptions();
- Usage currentUsage = (usage.isPresent()) ? getDefaultUsage(usage.get(), options)
- : getDefaultUsage(null, options);
- Usage cumulativeUsage = UsageCalculator.getCumulativeUsage(currentUsage, previousChatResponse);
- ChatResponse chatResponse = new ChatResponse(generations,
- toChatResponseMetadata(cumulativeUsage, generateContentResponse.modelVersion().get()));
-
- observationContext.setResponse(chatResponse);
- return chatResponse;
- }));
+ throw new RuntimeException(e);
+ }
+ });
if (this.toolExecutionEligibilityPredicate.isToolExecutionRequired(prompt.getOptions(), response)) {
var toolExecutionResult = this.toolCallingManager.executeToolCalls(prompt, response);
diff --git a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiChatModelCachedContentTests.java b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiChatModelCachedContentTests.java
index af4ea6679e0..f2340cc79d6 100644
--- a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiChatModelCachedContentTests.java
+++ b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiChatModelCachedContentTests.java
@@ -36,7 +36,7 @@
import org.springframework.ai.google.genai.cache.GoogleGenAiCachedContent;
import org.springframework.ai.google.genai.cache.GoogleGenAiCachedContentService;
import org.springframework.ai.retry.RetryUtils;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiChatModelExtendedUsageTests.java b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiChatModelExtendedUsageTests.java
index 27e3ccf24a5..1b75b991a3a 100644
--- a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiChatModelExtendedUsageTests.java
+++ b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiChatModelExtendedUsageTests.java
@@ -41,7 +41,7 @@
import org.springframework.ai.google.genai.metadata.GoogleGenAiTrafficType;
import org.springframework.ai.google.genai.metadata.GoogleGenAiUsage;
import org.springframework.ai.retry.RetryUtils;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiRetryTests.java b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiRetryTests.java
index 4170c992c64..901036959bc 100644
--- a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiRetryTests.java
+++ b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/GoogleGenAiRetryTests.java
@@ -27,10 +27,10 @@
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.ai.retry.RetryUtils;
-import org.springframework.retry.RetryCallback;
-import org.springframework.retry.RetryContext;
-import org.springframework.retry.RetryListener;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryListener;
+import org.springframework.core.retry.RetryPolicy;
+import org.springframework.core.retry.RetryTemplate;
+import org.springframework.core.retry.Retryable;
/**
* @author Mark Pollack
@@ -55,7 +55,7 @@ public class GoogleGenAiRetryTests {
public void setUp() {
this.retryTemplate = RetryUtils.SHORT_RETRY_TEMPLATE;
this.retryListener = new TestRetryListener();
- this.retryTemplate.registerListener(this.retryListener);
+ this.retryTemplate.setRetryListener(this.retryListener);
this.chatModel = new org.springframework.ai.google.genai.TestGoogleGenAiGeminiChatModel(this.genAiClient,
GoogleGenAiChatOptions.builder()
@@ -95,14 +95,15 @@ private static class TestRetryListener implements RetryListener {
int onSuccessRetryCount = 0;
@Override
- public void onSuccess(RetryContext context, RetryCallback callback, T result) {
- this.onSuccessRetryCount = context.getRetryCount();
+ public void beforeRetry(final RetryPolicy retryPolicy, final Retryable> retryable) {
+ // Count each retry attempt
+ this.onErrorRetryCount++;
}
@Override
- public void onError(RetryContext context, RetryCallback callback,
- Throwable throwable) {
- this.onErrorRetryCount = context.getRetryCount();
+ public void onRetrySuccess(final RetryPolicy retryPolicy, final Retryable> retryable, final Object result) {
+ // Count successful retries - we increment when we succeed after a failure
+ this.onSuccessRetryCount++;
}
}
diff --git a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/TestGoogleGenAiGeminiChatModel.java b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/TestGoogleGenAiGeminiChatModel.java
index 6c63133fd1f..2730b73e501 100644
--- a/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/TestGoogleGenAiGeminiChatModel.java
+++ b/models/spring-ai-google-genai/src/test/java/org/springframework/ai/google/genai/TestGoogleGenAiGeminiChatModel.java
@@ -20,7 +20,7 @@
import com.google.genai.types.GenerateContentResponse;
import org.springframework.ai.model.tool.ToolCallingManager;
-import org.springframework.retry.support.RetryTemplate;
+import org.springframework.core.retry.RetryTemplate;
/**
* @author Mark Pollack
diff --git a/models/spring-ai-huggingface/pom.xml b/models/spring-ai-huggingface/pom.xml
index fae8ecbd802..9c02044c248 100644
--- a/models/spring-ai-huggingface/pom.xml
+++ b/models/spring-ai-huggingface/pom.xml
@@ -90,7 +90,7 @@
io.swagger.codegen.v3
swagger-codegen-maven-plugin
- 3.0.64
+ 3.0.75
diff --git a/models/spring-ai-huggingface/src/main/resources/handlebars/Java/libraries/resttemplate/ApiClient.mustache b/models/spring-ai-huggingface/src/main/resources/handlebars/Java/libraries/resttemplate/ApiClient.mustache
new file mode 100644
index 00000000000..b08e07bd54f
--- /dev/null
+++ b/models/spring-ai-huggingface/src/main/resources/handlebars/Java/libraries/resttemplate/ApiClient.mustache
@@ -0,0 +1,651 @@
+package {{invokerPackage}};
+
+{{#withXml}}
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
+{{/withXml}}
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.InvalidMediaTypeException;
+import org.springframework.http.MediaType;
+import org.springframework.http.RequestEntity;
+import org.springframework.http.RequestEntity.BodyBuilder;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.BufferingClientHttpRequestFactory;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+{{#withXml}}
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
+{{/withXml}}
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+{{#threetenbp}}
+import org.threeten.bp.*;
+import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
+import com.fasterxml.jackson.databind.ObjectMapper;
+{{/threetenbp}}
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TimeZone;
+
+import {{invokerPackage}}.auth.Authentication;
+import {{invokerPackage}}.auth.HttpBasicAuth;
+import {{invokerPackage}}.auth.ApiKeyAuth;
+import {{invokerPackage}}.auth.OAuth;
+
+{{>generatedAnnotation}}
+@Component("{{invokerPackage}}.ApiClient")
+public class ApiClient {
+ public enum CollectionFormat {
+ CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null);
+
+ private final String separator;
+ private CollectionFormat(String separator) {
+ this.separator = separator;
+ }
+
+ private String collectionToString(Collection extends CharSequence> collection) {
+ return StringUtils.collectionToDelimitedString(collection, separator);
+ }
+ }
+
+ private boolean debugging = false;
+
+ private HttpHeaders defaultHeaders = new HttpHeaders();
+
+ private String basePath = "{{basePath}}";
+
+ private RestTemplate restTemplate;
+
+ private Map authentications;
+
+ private DateFormat dateFormat;
+
+ public ApiClient() {
+ this.restTemplate = buildRestTemplate();
+ init();
+ }
+
+ @Autowired
+ public ApiClient(RestTemplate restTemplate) {
+ this.restTemplate = restTemplate;
+ init();
+ }
+
+ protected void init() {
+ // Use RFC3339 format for date and datetime.
+ // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14
+ this.dateFormat = new RFC3339DateFormat();
+
+ // Use UTC as the default time zone.
+ this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+ // Set default User-Agent.
+ setUserAgent("Java-SDK");
+
+ // Setup authentications (key: authentication name, value: authentication).
+ authentications = new HashMap();{{#authMethods}}{{#isBasic}}
+ authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}}
+ authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
+ authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
+ // Prevent the authentications from being modified.
+ authentications = Collections.unmodifiableMap(authentications);
+ }
+
+ /**
+ * Get the current base path
+ * @return String the base path
+ */
+ public String getBasePath() {
+ return basePath;
+ }
+
+ /**
+ * Set the base path, which should include the host
+ * @param basePath the base path
+ * @return ApiClient this client
+ */
+ public ApiClient setBasePath(String basePath) {
+ this.basePath = basePath;
+ return this;
+ }
+
+ /**
+ * Get authentications (key: authentication name, value: authentication).
+ * @return Map the currently configured authentication types
+ */
+ public Map getAuthentications() {
+ return authentications;
+ }
+
+ /**
+ * Get authentication for the given name.
+ *
+ * @param authName The authentication name
+ * @return The authentication, null if not found
+ */
+ public Authentication getAuthentication(String authName) {
+ return authentications.get(authName);
+ }
+
+ /**
+ * Helper method to set username for the first HTTP basic authentication.
+ * @param username the username
+ */
+ public void setUsername(String username) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof HttpBasicAuth) {
+ ((HttpBasicAuth) auth).setUsername(username);
+ return;
+ }
+ }
+ throw new RuntimeException("No HTTP basic authentication configured!");
+ }
+
+ /**
+ * Helper method to set password for the first HTTP basic authentication.
+ * @param password the password
+ */
+ public void setPassword(String password) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof HttpBasicAuth) {
+ ((HttpBasicAuth) auth).setPassword(password);
+ return;
+ }
+ }
+ throw new RuntimeException("No HTTP basic authentication configured!");
+ }
+
+ /**
+ * Helper method to set API key value for the first API key authentication.
+ * @param apiKey the API key
+ */
+ public void setApiKey(String apiKey) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof ApiKeyAuth) {
+ ((ApiKeyAuth) auth).setApiKey(apiKey);
+ return;
+ }
+ }
+ throw new RuntimeException("No API key authentication configured!");
+ }
+
+ /**
+ * Helper method to set API key prefix for the first API key authentication.
+ * @param apiKeyPrefix the API key prefix
+ */
+ public void setApiKeyPrefix(String apiKeyPrefix) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof ApiKeyAuth) {
+ ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix);
+ return;
+ }
+ }
+ throw new RuntimeException("No API key authentication configured!");
+ }
+
+ /**
+ * Helper method to set access token for the first OAuth2 authentication.
+ * @param accessToken the access token
+ */
+ public void setAccessToken(String accessToken) {
+ for (Authentication auth : authentications.values()) {
+ if (auth instanceof OAuth) {
+ ((OAuth) auth).setAccessToken(accessToken);
+ return;
+ }
+ }
+ throw new RuntimeException("No OAuth2 authentication configured!");
+ }
+
+ /**
+ * Set the User-Agent header's value (by adding to the default header map).
+ * @param userAgent the user agent string
+ * @return ApiClient this client
+ */
+ public ApiClient setUserAgent(String userAgent) {
+ addDefaultHeader("User-Agent", userAgent);
+ return this;
+ }
+
+ /**
+ * Add a default header.
+ *
+ * @param name The header's name
+ * @param value The header's value
+ * @return ApiClient this client
+ */
+ public ApiClient addDefaultHeader(String name, String value) {
+ if (defaultHeaders.containsHeader(name)) {
+ defaultHeaders.remove(name);
+ }
+ defaultHeaders.add(name, value);
+ return this;
+ }
+
+ public void setDebugging(boolean debugging) {
+ List currentInterceptors = this.restTemplate.getInterceptors();
+ if(debugging) {
+ if (currentInterceptors == null) {
+ currentInterceptors = new ArrayList();
+ }
+ ClientHttpRequestInterceptor interceptor = new ApiClientHttpRequestInterceptor();
+ currentInterceptors.add(interceptor);
+ this.restTemplate.setInterceptors(currentInterceptors);
+ } else {
+ if (currentInterceptors != null && !currentInterceptors.isEmpty()) {
+ Iterator iter = currentInterceptors.iterator();
+ while (iter.hasNext()) {
+ ClientHttpRequestInterceptor interceptor = iter.next();
+ if (interceptor instanceof ApiClientHttpRequestInterceptor) {
+ iter.remove();
+ }
+ }
+ this.restTemplate.setInterceptors(currentInterceptors);
+ }
+ }
+ this.debugging = debugging;
+ }
+
+ /**
+ * Check that whether debugging is enabled for this API client.
+ * @return boolean true if this client is enabled for debugging, false otherwise
+ */
+ public boolean isDebugging() {
+ return debugging;
+ }
+
+ /**
+ * Get the date format used to parse/format date parameters.
+ * @return DateFormat format
+ */
+ public DateFormat getDateFormat() {
+ return dateFormat;
+ }
+
+ /**
+ * Set the date format used to parse/format date parameters.
+ * @param dateFormat Date format
+ * @return API client
+ */
+ public ApiClient setDateFormat(DateFormat dateFormat) {
+ this.dateFormat = dateFormat;
+ {{#threetenbp}}
+ for(HttpMessageConverter converter:restTemplate.getMessageConverters()){
+ if(converter instanceof AbstractJackson2HttpMessageConverter){
+ ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter)converter).getObjectMapper();
+ mapper.setDateFormat(dateFormat);
+ }
+ }
+ {{/threetenbp}}
+ return this;
+ }
+
+ /**
+ * Parse the given string into Date object.
+ */
+ public Date parseDate(String str) {
+ try {
+ return dateFormat.parse(str);
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Format the given Date object into string.
+ */
+ public String formatDate(Date date) {
+ return dateFormat.format(date);
+ }
+
+ /**
+ * Format the given parameter object into string.
+ * @param param the object to convert
+ * @return String the parameter represented as a String
+ */
+ public String parameterToString(Object param) {
+ if (param == null) {
+ return "";
+ } else if (param instanceof Date) {
+ return formatDate( (Date) param);
+ } else if (param instanceof Collection) {
+ StringBuilder b = new StringBuilder();
+ for(Object o : (Collection>) param) {
+ if(b.length() > 0) {
+ b.append(",");
+ }
+ b.append(String.valueOf(o));
+ }
+ return b.toString();
+ } else {
+ return String.valueOf(param);
+ }
+ }
+
+ /**
+ * Converts a parameter to a {@link MultiValueMap} for use in REST requests
+ * @param collectionFormat The format to convert to
+ * @param name The name of the parameter
+ * @param value The parameter's value
+ * @return a Map containing the String value(s) of the input parameter
+ */
+ public MultiValueMap parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) {
+ final MultiValueMap params = new LinkedMultiValueMap();
+
+ if (name == null || name.isEmpty() || value == null) {
+ return params;
+ }
+
+ if(collectionFormat == null) {
+ collectionFormat = CollectionFormat.CSV;
+ }
+
+ Collection> valueCollection = null;
+ if (value instanceof Collection) {
+ valueCollection = (Collection>) value;
+ } else {
+ params.add(name, parameterToString(value));
+ return params;
+ }
+
+ if (valueCollection.isEmpty()){
+ return params;
+ }
+
+ if (collectionFormat.equals(CollectionFormat.MULTI)) {
+ for (Object item : valueCollection) {
+ params.add(name, parameterToString(item));
+ }
+ return params;
+ }
+
+ List values = new ArrayList();
+ for(Object o : valueCollection) {
+ values.add(parameterToString(o));
+ }
+ params.add(name, collectionFormat.collectionToString(values));
+
+ return params;
+ }
+
+ /**
+ * Check if the given {@code String} is a JSON MIME.
+ * @param mediaType the input MediaType
+ * @return boolean true if the MediaType represents JSON, false otherwise
+ */
+ public boolean isJsonMime(String mediaType) {
+ // "* / *" is default to JSON
+ if ("*/*".equals(mediaType)) {
+ return true;
+ }
+
+ try {
+ return isJsonMime(MediaType.parseMediaType(mediaType));
+ } catch (InvalidMediaTypeException e) {
+ }
+ return false;
+ }
+
+ /**
+ * Check if the given MIME is a JSON MIME.
+ * JSON MIME examples:
+ * application/json
+ * application/json; charset=UTF8
+ * APPLICATION/JSON
+ * @param mediaType the input MediaType
+ * @return boolean true if the MediaType represents JSON, false otherwise
+ */
+ public boolean isJsonMime(MediaType mediaType) {
+ return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$"));
+ }
+
+ /**
+ * Select the Accept header's value from the given accepts array:
+ * if JSON exists in the given array, use it;
+ * otherwise use all of them (joining into a string)
+ *
+ * @param accepts The accepts array to select from
+ * @return List The list of MediaTypes to use for the Accept header
+ */
+ public List selectHeaderAccept(String[] accepts) {
+ if (accepts.length == 0) {
+ return null;
+ }
+ for (String accept : accepts) {
+ MediaType mediaType = MediaType.parseMediaType(accept);
+ if (isJsonMime(mediaType)) {
+ return Collections.singletonList(mediaType);
+ }
+ }
+ return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(accepts));
+ }
+
+ /**
+ * Select the Content-Type header's value from the given array:
+ * if JSON exists in the given array, use it;
+ * otherwise use the first one of the array.
+ *
+ * @param contentTypes The Content-Type array to select from
+ * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used.
+ */
+ public MediaType selectHeaderContentType(String[] contentTypes) {
+ if (contentTypes.length == 0) {
+ return MediaType.APPLICATION_JSON;
+ }
+ for (String contentType : contentTypes) {
+ MediaType mediaType = MediaType.parseMediaType(contentType);
+ if (isJsonMime(mediaType)) {
+ return mediaType;
+ }
+ }
+ return MediaType.parseMediaType(contentTypes[0]);
+ }
+
+ /**
+ * Select the body to use for the request
+ * @param obj the body object
+ * @param formParams the form parameters
+ * @param contentType the content type of the request
+ * @return Object the selected body
+ */
+ protected Object selectBody(Object obj, MultiValueMap formParams, MediaType contentType) {
+ boolean isForm = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType);
+ return isForm ? formParams : obj;
+ }
+
+ /**
+ * Invoke API by sending HTTP request with the given options.
+ *
+ * @param the return type to use
+ * @param path The sub-path of the HTTP URL
+ * @param method The request method
+ * @param queryParams The query parameters
+ * @param body The request body object
+ * @param headerParams The header parameters
+ * @param formParams The form parameters
+ * @param accept The request's Accept header
+ * @param contentType The request's Content-Type header
+ * @param authNames The authentications to apply
+ * @param returnType The return type into which to deserialize the response
+ * @return ResponseEntity<T> The response of the chosen type
+ */
+ public ResponseEntity invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException {
+ updateParamsForAuth(authNames, queryParams, headerParams);
+
+ final UriComponentsBuilder builder = UriComponentsBuilder.fromPath(basePath).path(path);
+ if (queryParams != null) {
+ builder.queryParams(queryParams);
+ }
+
+ final BodyBuilder requestBuilder = RequestEntity.method(method, builder.build().toUri());
+ if(accept != null) {
+ requestBuilder.accept(accept.toArray(new MediaType[accept.size()]));
+ }
+ if(contentType != null) {
+ requestBuilder.contentType(contentType);
+ }
+
+ addHeadersToRequest(headerParams, requestBuilder);
+ addHeadersToRequest(defaultHeaders, requestBuilder);
+
+ RequestEntity