From 18780c158e4cc38ff2d676e5bc78786943c78a8e Mon Sep 17 00:00:00 2001 From: matejnedic Date: Sun, 20 Jul 2025 13:14:09 +0200 Subject: [PATCH 1/4] Introduce S3 Vector Client support --- docs/src/main/asciidoc/s3.adoc | 44 ++++++- spring-cloud-aws-autoconfigure/pom.xml | 6 + .../s3/S3VectorClientAutoConfiguration.java | 52 ++++++++ .../s3/S3VectorClientCustomizer.java | 15 +++ .../s3/properties/S3VectorProperties.java | 19 +++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../s3/S3VectorAutoConfigurationTests.java | 45 +++++++ .../s3/S3VectorClientCustomizerTests.java | 112 ++++++++++++++++++ spring-cloud-aws-dependencies/pom.xml | 2 +- 9 files changed, 290 insertions(+), 6 deletions(-) create mode 100644 spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java create mode 100644 spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizer.java create mode 100644 spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/properties/S3VectorProperties.java create mode 100644 spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java create mode 100644 spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizerTests.java diff --git a/docs/src/main/asciidoc/s3.adoc b/docs/src/main/asciidoc/s3.adoc index 6a9fc318a..9391dff14 100644 --- a/docs/src/main/asciidoc/s3.adoc +++ b/docs/src/main/asciidoc/s3.adoc @@ -604,17 +604,51 @@ The Spring Boot Starter for S3 provides the following configuration options: | `spring.cloud.aws.s3.config.reload.max-wait-time-for-restart` | `Duration`| `2s` | The maximum time between the detection of changes in property source and the application context restart when `restart_context` strategy is used. |=== +=== S3 Vector Client support + +https://aws.amazon.com/blogs/aws/introducing-amazon-s3-vectors-first-cloud-storage-with-native-vector-support-at-scale/[S3 Vector Store] is a vector storage which supports uploading, storing and querying vectors. +To allow users simpler use of `S3VectorsClient` with https://github.com/spring-projects/spring-ai[Spring AI] project or use of a plain client, we support autoconfiguration of the `S3VectorsClient`. + +To enable autoconfiguration you should add the following dependencies +[source,xml] +---- + + io.awspring.cloud + spring-cloud-aws-starter + + + + software.amazon.awssdk + s3vectors + +---- + +After dependencies are introduced Spring Cloud AWS will automatically create a `S3VectorsClient` bean which can than be autowired and used. + +[cols="2,3,1,1"] +|=== +| Name | Description | Required | Default value +| `spring.cloud.aws.s3.vector.config.enabled` | Enables the S3 config import integration. | No | `true` +| `spring.cloud.aws.s3.config.reload.strategy` | `Enum` | `refresh` | The strategy to use when firing a reload (`refresh`, `restart_context`) +| `spring.cloud.aws.s3.config.reload.period` | `Duration`| `15s` | The period for verifying changes +| `spring.cloud.aws.s3.config.reload.max-wait-time-for-restart` | `Duration`| `2s` | The maximum time between the detection of changes in property source and the application context restart when `restart_context` strategy is used. +|=== === IAM Permissions Following IAM permissions are required by Spring Cloud AWS: -[cols="2,1"] -|=== -| Downloading files | `s3:GetObject` -| Searching files | `s3:ListObjects` -| Uploading files | `s3:PutObject` +[cols="2,3,1,1"] |=== +| Name | Description | Required | Default value +| `spring.cloud.aws.s3.vector.enabled` | Enables the S3VectorsClient autoconfiguration. | No | `true` +| `spring.cloud.aws.s3.vector.endpoint` | Configures endpoint used by `S3VectorsClient`. | No | `http://localhost:4566` +| `spring.cloud.aws.s3.vector.region` | Configures region used by `S3VectorsClient`. | No | `eu-west-1` + + + + +=== Example of IAM policy for Spring Cloud AWS demo bucket Sample IAM policy granting access to `spring-cloud-aws-demo` bucket: diff --git a/spring-cloud-aws-autoconfigure/pom.xml b/spring-cloud-aws-autoconfigure/pom.xml index fade54b61..bd44c615d 100644 --- a/spring-cloud-aws-autoconfigure/pom.xml +++ b/spring-cloud-aws-autoconfigure/pom.xml @@ -176,6 +176,12 @@ amazon-s3-encryption-client-java true + + + software.amazon.awssdk + s3vectors + true + io.micrometer micrometer-observation-test diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java new file mode 100644 index 000000000..9c94ba4be --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java @@ -0,0 +1,52 @@ +package io.awspring.cloud.autoconfigure.s3; + +import io.awspring.cloud.autoconfigure.AwsSyncClientCustomizer; +import io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer; +import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; +import io.awspring.cloud.autoconfigure.core.AwsConnectionDetails; +import io.awspring.cloud.autoconfigure.core.AwsProperties; +import io.awspring.cloud.autoconfigure.s3.properties.S3VectorProperties; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import software.amazon.awssdk.services.s3vectors.S3VectorsClient; +import software.amazon.awssdk.services.s3vectors.S3VectorsClientBuilder; + +/** + * @author Matej Nedic + * @since 3.5.0 + */ +@AutoConfiguration +@ConditionalOnClass({S3VectorsClient.class}) +@EnableConfigurationProperties({S3VectorProperties.class, AwsProperties.class}) +@ConditionalOnProperty(name = "spring.cloud.aws.s3.vector.enabled", havingValue = "true", matchIfMissing = true) +public class S3VectorClientAutoConfiguration { + + private final S3VectorProperties properties; + + public S3VectorClientAutoConfiguration(S3VectorProperties properties) { + this.properties = properties; + } + + @Bean + @ConditionalOnMissingBean + S3VectorsClientBuilder s3ClientBuilder(AwsClientBuilderConfigurer awsClientBuilderConfigurer, + ObjectProvider> configurer, + ObjectProvider connectionDetails, + ObjectProvider s3ClientCustomizers, + ObjectProvider awsSyncClientCustomizers) { + + return awsClientBuilderConfigurer.configureSyncClient(S3VectorsClient.builder(), this.properties, + connectionDetails.getIfAvailable(), configurer.getIfAvailable(), s3ClientCustomizers.orderedStream(), + awsSyncClientCustomizers.orderedStream()); + } + + @Bean + S3VectorsClient s3VectorsClient(S3VectorsClientBuilder builder) { + return builder.build(); + } +} diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizer.java new file mode 100644 index 000000000..a132ca901 --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizer.java @@ -0,0 +1,15 @@ +package io.awspring.cloud.autoconfigure.s3; + +import io.awspring.cloud.autoconfigure.AwsClientCustomizer; +import software.amazon.awssdk.services.s3.S3ClientBuilder; +import software.amazon.awssdk.services.s3vectors.S3VectorsClientBuilder; + +/** + * Callback interface that can be used to customize a {@link S3ClientBuilder}. + * + * @author Matej Nedic + * @since 3.5.0 + */ +@FunctionalInterface +public interface S3VectorClientCustomizer extends AwsClientCustomizer { +} diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/properties/S3VectorProperties.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/properties/S3VectorProperties.java new file mode 100644 index 000000000..6303b662e --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/properties/S3VectorProperties.java @@ -0,0 +1,19 @@ +package io.awspring.cloud.autoconfigure.s3.properties; + +import io.awspring.cloud.autoconfigure.AwsClientProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; + + +/** + * @author Matej Nedic + */ +@ConfigurationProperties(prefix = S3VectorProperties.PREFIX) +public class S3VectorProperties extends AwsClientProperties { + + /** + * The prefix used for S3 related properties. + */ + public static final String PREFIX = "spring.cloud.aws.s3.vector"; + + +} diff --git a/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 657cbf245..9e5b9c476 100644 --- a/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -7,6 +7,7 @@ io.awspring.cloud.autoconfigure.ses.SesAutoConfiguration io.awspring.cloud.autoconfigure.s3.S3TransferManagerAutoConfiguration io.awspring.cloud.autoconfigure.s3.S3AutoConfiguration io.awspring.cloud.autoconfigure.s3.S3CrtAsyncClientAutoConfiguration +io.awspring.cloud.autoconfigure.s3.S3VectorClientAutoConfiguration io.awspring.cloud.autoconfigure.sns.SnsAutoConfiguration io.awspring.cloud.autoconfigure.sqs.SqsAutoConfiguration io.awspring.cloud.autoconfigure.dynamodb.DynamoDbAutoConfiguration diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java new file mode 100644 index 000000000..7b6893091 --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java @@ -0,0 +1,45 @@ +package io.awspring.cloud.autoconfigure.s3; + +import io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration; +import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; +import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; +import io.awspring.cloud.autoconfigure.s3.properties.S3Properties; +import io.awspring.cloud.s3.S3OutputStreamProvider; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3ClientBuilder; +import software.amazon.awssdk.services.s3vectors.S3VectorsClient; +import software.amazon.encryption.s3.S3EncryptionClient; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test for {@link S3AutoConfiguration} class + * + * @author Matej Nedic + */ +public class S3VectorAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") + .withConfiguration(AutoConfigurations.of(AwsAutoConfiguration.class, RegionProviderAutoConfiguration.class, + CredentialsProviderAutoConfiguration.class, S3VectorClientAutoConfiguration.class)); + + + @Test + void createsS3VectorClientBean() { + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(S3VectorsClient.class); + }); + } + + @Test + void s3VectorClientAutoConfigurationIsDisabled() { + this.contextRunner.withPropertyValues("spring.cloud.aws.s3.vector.enabled:false").run(context -> { + assertThat(context).doesNotHaveBean(S3VectorsClient.class); + }); + } +} diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizerTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizerTests.java new file mode 100644 index 000000000..3ec752f68 --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientCustomizerTests.java @@ -0,0 +1,112 @@ +package io.awspring.cloud.autoconfigure.s3; + +import io.awspring.cloud.autoconfigure.AwsSyncClientCustomizer; +import io.awspring.cloud.autoconfigure.ConfiguredAwsClient; +import io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration; +import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; +import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.services.s3vectors.S3VectorsClient; + +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * Tests for {@link S3VectorClientCustomizer}. + * + * @author Matej Nedic + * @author Maciej Walkowiak + */ +public class S3VectorClientCustomizerTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withPropertyValues("spring.cloud.aws.region.static:eu-west-1", + "spring.cloud.aws.credentials.access-key:noop", "spring.cloud.aws.credentials.secret-key:noop") + .withConfiguration(AutoConfigurations.of(AwsAutoConfiguration.class, RegionProviderAutoConfiguration.class, + CredentialsProviderAutoConfiguration.class, S3VectorClientAutoConfiguration.class)); + + @Test + void customClientCustomizer() { + contextRunner.withUserConfiguration(S3VectorClientCustomizerTests.CustomizerConfig.class).run(context -> { + ConfiguredAwsClient client = new ConfiguredAwsClient(context.getBean(S3VectorsClient.class)); + assertThat(client.getApiCallTimeout()).describedAs("sets property from first customizer") + .isEqualTo(Duration.ofMillis(2001)); + assertThat(client.getApiCallAttemptTimeout()).describedAs("sets property from second customizer") + .isEqualTo(Duration.ofMillis(2002)); + assertThat(client.getSyncHttpClient()).describedAs("sets property from common client customizer") + .isNotNull(); + }); + } + + @Test + void customClientCustomizerWithOrder() { + contextRunner.withUserConfiguration(S3VectorClientCustomizerTests.CustomizerConfigWithOrder.class).run(context -> { + ConfiguredAwsClient client = new ConfiguredAwsClient(context.getBean(S3VectorsClient.class)); + assertThat(client.getApiCallTimeout()) + .describedAs("property from the customizer with higher order takes precedence") + .isEqualTo(Duration.ofMillis(2001)); + }); + } + + + @Configuration(proxyBeanMethods = false) + static class CustomizerConfig { + + @Bean + S3VectorClientCustomizer customizer() { + return builder -> { + builder.overrideConfiguration(builder.overrideConfiguration().copy(c -> { + c.apiCallTimeout(Duration.ofMillis(2001)); + })); + }; + } + + @Bean + S3VectorClientCustomizer customizer2() { + return builder -> { + builder.overrideConfiguration(builder.overrideConfiguration().copy(c -> { + c.apiCallAttemptTimeout(Duration.ofMillis(2002)); + })); + }; + } + + @Bean + AwsSyncClientCustomizer awsSyncClientCustomizer() { + return builder -> { + builder.httpClient(ApacheHttpClient.builder().connectionTimeout(Duration.ofMillis(1542)).build()); + }; + } + } + + @Configuration(proxyBeanMethods = false) + static class CustomizerConfigWithOrder { + + @Bean + @Order(2) + S3VectorClientCustomizer customizer() { + return builder -> { + builder.overrideConfiguration(builder.overrideConfiguration().copy(c -> { + c.apiCallTimeout(Duration.ofMillis(2001)); + })); + }; + } + + @Bean + @Order(1) + S3VectorClientCustomizer customizer2() { + return builder -> { + builder.overrideConfiguration(builder.overrideConfiguration().copy(c -> { + c.apiCallTimeout(Duration.ofMillis(2000)); + })); + }; + } + } +} diff --git a/spring-cloud-aws-dependencies/pom.xml b/spring-cloud-aws-dependencies/pom.xml index 8c12a8777..33e3e4dce 100644 --- a/spring-cloud-aws-dependencies/pom.xml +++ b/spring-cloud-aws-dependencies/pom.xml @@ -24,7 +24,7 @@ 2.31.0 - 2.29.52 + 2.32.4 2.0.5 3.3.0 1.6 From 7e9451561b6f6289e145ee68fec9d94f4fcbd913 Mon Sep 17 00:00:00 2001 From: matejnedic Date: Sun, 20 Jul 2025 14:35:15 +0200 Subject: [PATCH 2/4] polish --- .../autoconfigure/s3/S3VectorAutoConfigurationTests.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java index 7b6893091..306d765d8 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3VectorAutoConfigurationTests.java @@ -3,16 +3,10 @@ import io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; -import io.awspring.cloud.autoconfigure.s3.properties.S3Properties; -import io.awspring.cloud.s3.S3OutputStreamProvider; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.S3ClientBuilder; import software.amazon.awssdk.services.s3vectors.S3VectorsClient; -import software.amazon.encryption.s3.S3EncryptionClient; import static org.assertj.core.api.Assertions.assertThat; From ef6735d065bccfc3bc962723e7da0b3317847f89 Mon Sep 17 00:00:00 2001 From: matejnedic Date: Sun, 20 Jul 2025 14:46:44 +0200 Subject: [PATCH 3/4] polish --- .../cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java index 9c94ba4be..5bcef83e1 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java @@ -34,7 +34,7 @@ public S3VectorClientAutoConfiguration(S3VectorProperties properties) { @Bean @ConditionalOnMissingBean - S3VectorsClientBuilder s3ClientBuilder(AwsClientBuilderConfigurer awsClientBuilderConfigurer, + S3VectorsClientBuilder s3VectorsClientBuilder(AwsClientBuilderConfigurer awsClientBuilderConfigurer, ObjectProvider> configurer, ObjectProvider connectionDetails, ObjectProvider s3ClientCustomizers, From 9e97ad25139d8c654c5714c55bd54c24b3251cf7 Mon Sep 17 00:00:00 2001 From: matejnedic Date: Mon, 21 Jul 2025 20:00:32 +0200 Subject: [PATCH 4/4] Update --- .../autoconfigure/s3/S3VectorClientAutoConfiguration.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java index 5bcef83e1..035de8f98 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3VectorClientAutoConfiguration.java @@ -1,13 +1,11 @@ package io.awspring.cloud.autoconfigure.s3; import io.awspring.cloud.autoconfigure.AwsSyncClientCustomizer; -import io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer; -import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; -import io.awspring.cloud.autoconfigure.core.AwsConnectionDetails; -import io.awspring.cloud.autoconfigure.core.AwsProperties; +import io.awspring.cloud.autoconfigure.core.*; import io.awspring.cloud.autoconfigure.s3.properties.S3VectorProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -23,6 +21,7 @@ @AutoConfiguration @ConditionalOnClass({S3VectorsClient.class}) @EnableConfigurationProperties({S3VectorProperties.class, AwsProperties.class}) +@AutoConfigureAfter({ CredentialsProviderAutoConfiguration.class, RegionProviderAutoConfiguration.class }) @ConditionalOnProperty(name = "spring.cloud.aws.s3.vector.enabled", havingValue = "true", matchIfMissing = true) public class S3VectorClientAutoConfiguration {