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 93e5c2640cf..c1d0a50b779 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 @@ -30,7 +30,6 @@ import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -49,16 +48,15 @@ * @author Christian Tzolov * @author Thomas Vitale * @author Ilayaperumal Gopinathan + * @author Hyoseop Song * @since 1.0.0 */ -@AutoConfiguration(after = { RestClientAutoConfiguration.class, SpringAiRetryAutoConfiguration.class, - ToolCallingAutoConfiguration.class, WebClientAutoConfiguration.class }) +@AutoConfiguration(after = { RestClientAutoConfiguration.class, WebClientAutoConfiguration.class, + ToolCallingAutoConfiguration.class, SpringAiRetryAutoConfiguration.class }) @EnableConfigurationProperties({ AnthropicChatProperties.class, AnthropicConnectionProperties.class }) @ConditionalOnClass(AnthropicApi.class) @ConditionalOnProperty(name = SpringAIModelProperties.CHAT_MODEL, havingValue = SpringAIModels.ANTHROPIC, matchIfMissing = true) -@ImportAutoConfiguration(classes = { SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - ToolCallingAutoConfiguration.class, WebClientAutoConfiguration.class }) public class AnthropicChatAutoConfiguration { @Bean diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfigurationIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfigurationIT.java index 89c68d939bf..3d09f769972 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfigurationIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicChatAutoConfigurationIT.java @@ -33,7 +33,6 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.model.Generation; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -45,7 +44,7 @@ public class AnthropicChatAutoConfigurationIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.apiKey=" + System.getenv("ANTHROPIC_API_KEY")) - .withConfiguration(AutoConfigurations.of(AnthropicChatAutoConfiguration.class)); + .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)); @Test void call() { diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicModelConfigurationTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicModelConfigurationTests.java index dae74691d03..cdb00ee6af5 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicModelConfigurationTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/AnthropicModelConfigurationTests.java @@ -19,7 +19,6 @@ import org.junit.jupiter.api.Test; import org.springframework.ai.anthropic.AnthropicChatModel; -import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -33,7 +32,7 @@ public class AnthropicModelConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.apiKey=" + System.getenv("ANTHROPIC_API_KEY")) - .withConfiguration(AutoConfigurations.of(AnthropicChatAutoConfiguration.class)); + .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)); @Test void chatModelActivation() { 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 5d4f5804da3..976a3d04cc1 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 @@ -44,8 +44,7 @@ public void connectionProperties() { "spring.ai.anthropic.chat.options.model=MODEL_XYZ", "spring.ai.anthropic.chat.options.temperature=0.55") // @formatter:on - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, AnthropicChatAutoConfiguration.class)) + .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(AnthropicChatProperties.class); var connectionProperties = context.getBean(AnthropicConnectionProperties.class); @@ -79,8 +78,7 @@ public void chatOptionsTest() { "spring.ai.anthropic.chat.options.top-k=100" ) // @formatter:on - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, AnthropicChatAutoConfiguration.class)) + .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) .run(context -> { var chatProperties = context.getBean(AnthropicChatProperties.class); var connectionProperties = context.getBean(AnthropicConnectionProperties.class); @@ -103,8 +101,7 @@ public void chatCompletionDisabled() { // It is enabled by default new ApplicationContextRunner().withPropertyValues("spring.ai.anthropic.api-key=API_KEY") - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, AnthropicChatAutoConfiguration.class)) + .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AnthropicChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(AnthropicChatModel.class)).isNotEmpty(); @@ -113,8 +110,7 @@ public void chatCompletionDisabled() { // Explicitly enable the chat auto-configuration. new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.api-key=API_KEY", "spring.ai.model.chat=anthropic") - .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, - RestClientAutoConfiguration.class, AnthropicChatAutoConfiguration.class)) + .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) .run(context -> { assertThat(context.getBeansOfType(AnthropicChatProperties.class)).isNotEmpty(); assertThat(context.getBeansOfType(AnthropicChatModel.class)).isNotEmpty(); 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 new file mode 100644 index 00000000000..c68d9188e10 --- /dev/null +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/BaseAnthropicIT.java @@ -0,0 +1,37 @@ +/* + * Copyright 2025-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.model.anthropic.autoconfigure; + +import java.util.Arrays; +import java.util.stream.Stream; + +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; + +public abstract class BaseAnthropicIT { + + public static AutoConfigurations anthropicAutoConfig(Class... additional) { + Class[] dependencies = { SpringAiRetryAutoConfiguration.class, ToolCallingAutoConfiguration.class, + RestClientAutoConfiguration.class, WebClientAutoConfiguration.class }; + Class[] all = Stream.concat(Arrays.stream(dependencies), Arrays.stream(additional)).toArray(Class[]::new); + return AutoConfigurations.of(all); + } + +} diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java index 91efc4bd6f9..1c34450d84a 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithFunctionBeanIT.java @@ -31,10 +31,10 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration; +import org.springframework.ai.model.anthropic.autoconfigure.BaseAnthropicIT; import org.springframework.ai.model.anthropic.autoconfigure.tool.MockWeatherService.Request; import org.springframework.ai.model.anthropic.autoconfigure.tool.MockWeatherService.Response; import org.springframework.ai.model.tool.ToolCallingChatOptions; -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; @@ -49,7 +49,7 @@ class FunctionCallWithFunctionBeanIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.apiKey=" + System.getenv("ANTHROPIC_API_KEY")) - .withConfiguration(AutoConfigurations.of(AnthropicChatAutoConfiguration.class)) + .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)) .withUserConfiguration(Config.class); @Test diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java index a32f682e40d..50e336aa162 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-anthropic/src/test/java/org/springframework/ai/model/anthropic/autoconfigure/tool/FunctionCallWithPromptFunctionIT.java @@ -30,8 +30,8 @@ import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration; +import org.springframework.ai.model.anthropic.autoconfigure.BaseAnthropicIT; import org.springframework.ai.tool.function.FunctionToolCallback; -import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; @@ -43,7 +43,7 @@ public class FunctionCallWithPromptFunctionIT { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.ai.anthropic.apiKey=" + System.getenv("ANTHROPIC_API_KEY")) - .withConfiguration(AutoConfigurations.of(AnthropicChatAutoConfiguration.class)); + .withConfiguration(BaseAnthropicIT.anthropicAutoConfig(AnthropicChatAutoConfiguration.class)); @Test void functionCallTest() {