[google-adk-spring-ai] SpringAI beans are never auto-configured: @ConditionalOnBean(ChatModel) is evaluated before Spring AI model auto-configurations (missing ordering declaration)
维护者通常 1 天内回复
评估
这个 Issue 还没有评估数据。
描述
Environment
| Component | Version |
|---|---|
| google-adk / google-adk-spring-ai | 1.9.0 |
| Spring AI (BOM) | 2.0.1 |
| Spring Boot | 4.0.2 |
| Java | 25 |
Minimal reproduction
pom.xml (relevant parts):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.2</version>
</parent>
<properties>
<java.version>25</java.version>
<spring-ai.version>2.0.1</spring-ai.version>
<adk.version>1.9.0</adk.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk</artifactId>
<version>${adk.version}</version>
</dependency>
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-spring-ai</artifactId>
<version>${adk.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Application.java:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
LlmAgent agent(SpringAI springAI) {
return LlmAgent.builder()
.name("demo-agent")
.model(springAI)
.instruction("You are a helpful assistant.")
.build();
}
}
application.yaml (dummy values are enough — the failure happens at bean-definition processing, before any remote call):
spring:
ai:
openai:
base-url: https://api.openai.com
api-key: dummy
chat:
model: gpt-4o-mini
Run: mvn spring-boot:run
Actual behavior
Application fails to start:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method agent in com.example.demo.DemoApplication required a bean
of type 'com.google.adk.models.springai.SpringAI' that could not be found.
Action:
Consider defining a bean of type 'com.google.adk.models.springai.SpringAI' in your configuration.
Running with --debug shows the root cause — the OpenAI ChatModel bean definition is registered, but SpringAIAutoConfiguration is processed before it, so all three SpringAI @Bean methods are skipped:
OpenAiChatAutoConfiguration matched:
- @ConditionalOnProperty (spring.ai.model.chat=openai) matched
OpenAiChatAutoConfiguration#openAiChatModel matched:
- @ConditionalOnMissingBean ... did not find any beans (OnBeanCondition)
SpringAIAutoConfiguration#springAIWithBothModels:
Did not match:
- @ConditionalOnBean (types: ...ChatModel, ...StreamingChatModel) did not find any beans
SpringAIAutoConfiguration#springAIWithChatModel:
Did not match:
- @ConditionalOnBean (types: ...ChatModel) did not find any beans of type ...ChatModel (OnBeanCondition)
SpringAIAutoConfiguration#springAIWithStreamingModel:
Did not match:
- @ConditionalOnBean (types: ...StreamingChatModel) did not find any beans
Note springAIEmbedding has the same problem (@ConditionalOnBean(EmbeddingModel.class)) — it fails silently (no bean, no error), which makes it even harder to notice.
Expected behavior
SpringAIAutoConfiguration registers a SpringAI bean whenever a ChatModel (and/or StreamingChatModel) is defined by Spring AI model auto-configurations, regardless of which provider starter is used.
Root cause
SpringAIAutoConfiguration guards its @Bean methods with @ConditionalOnBean(...), but declares no ordering relative to the auto-configurations that may provide those beans. Per the Spring Boot reference documentation, the result of @ConditionalOnBean depends on what has been processed so far, so an auto-configuration relying on it must be ordered after the configurations that register the matched beans.
google-adk-spring-ai 1.9.0 is built against Spring AI 2.x / Boot 4 (its POM depends on spring-ai-model:2.0.1 and spring-boot-autoconfigure:4.0.2), and since it compiles only against spring-ai-model (no provider modules), the Class-based after = ... attribute is not usable here — the string-based afterName attribute exists exactly for this case (non-existent class names are silently ignored by the sorter).
Suggested fix
Add an afterName list covering the Spring AI model auto-configurations, mirroring what Spring AI 1.x's own ChatClientAutoConfiguration did for the identical scenario (@ConditionalOnBean(ChatModel) with an unpredictable provider):
-@AutoConfiguration
+@AutoConfiguration(afterName = {
+ "org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration",
+ "org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration",
+ // remaining Spring AI 2.x model auto-configurations, e.g.:
+ // org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration
+ // org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration
+ // ... (package pattern: org.springframework.ai.model.<provider>.autoconfigure.*)
+})
@ConditionalOnClass({SpringAI.class, ChatModel.class})
@ConditionalOnProperty(prefix = "adk.spring-ai.auto-configuration", name = "enabled",
havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties({SpringAIProperties.class})
public class SpringAIAutoConfiguration {
(Verified against Spring AI 2.0.1: org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration / OpenAiEmbeddingAutoConfiguration. The other provider names above follow the 2.x package pattern and should be double-checked against the current source.)
An alternative design — the one Spring AI 2.0 itself adopted — is to drop the @ConditionalOnBean guards entirely and take ChatModel/StreamingChatModel as @Bean method parameters, which removes the ordering sensitivity altogether. The afterName fix is the smaller, backward-compatible change, though.
Workaround (for users on 1.9.0)
Define the SpringAI bean in application code — user-defined beans are processed before auto-configurations, and ADK's @ConditionalOnMissingBean(SpringAI.class) then backs off:
@Bean
SpringAI springAI(ChatModel chatModel) {
return new SpringAI(chatModel, "gpt-4o-mini");
}
This works with any provider (it consumes the ChatModel abstraction), but every project using ADK + Spring AI has to copy it, so it is not a substitute for the upstream fix.
References
- Spring Boot reference — Creating your own auto-configuration / condition annotations: ordering matters for
@ConditionalOnBean - Spring AI 1.x
ChatClientAutoConfiguration: same pattern solved withafterNameover all provider auto-configurations - Spring AI 2.0.1
ChatClientAutoConfiguration: same problem avoided via@Beanparameter injection instead of@ConditionalOnBean
- 主要语言
- Java
- 星标
- 1.7k
- 派生
- 433
- 平均合并
- 3 天 13 小时
- 30 天内合并 PR
- 42
环境准备
在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
google/adk-java 的其他 Issue
-
GeminiUtil placeholder user turn ("Continue output. DO NOT look at this line ...") is flagged by prompt injection filters可能已有人在做 @hemasekhar-p 于 2 天前认领。 未关闭needs review
难度 2/5 1-3 小时 新手友好度 76/100
google/adk-java#1628 · 1 条评论 · 已指派 1 人 ·
维护者通常 1 天内回复
-
[spring-ai] ToolConverter silently drops enum and items from tool parameter schemas可能已有人在做 @hirematha 于 5 天前认领。 未关闭needs review
难度 2/5 1-3 小时 新手友好度 76/100
google/adk-java#1609 · 2 条评论 · 已指派 1 人 ·
维护者通常 1 天内回复
-
[spring-ai] Streaming responses ending with CJK punctuation (。!?) are misclassified as partial and never persisted to the session可能已有人在做 @hirematha 于 5 天前认领。 未关闭needs review
难度 2/5 1-3 小时 新手友好度 84/100
google/adk-java#1608 · 3 条评论 · 已指派 1 人 ·
维护者通常 1 天内回复
-
FirestoreSessionService compares event timestamps as text, reordering or skipping same-second events未关闭
难度 3/5 1-2 天 新手友好度 50/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 45/100
维护者通常 1 天内回复
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 62/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 85/100
objectionary/eo-graphs#80 ·
-
难度 2/5 1-3 小时 新手友好度 78/100
objectionary/jucs#141 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 74/100
-
bug good first issue
难度 2/5 1-3 小时 新手友好度 88/100
repowise-dev/repowise#3335 ·
维护者通常 1 天内回复