diff --git a/spring-ai-core/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java b/spring-ai-core/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java index feaafd80130..f5f601724df 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java @@ -152,6 +152,16 @@ else if (isParamMismatch(uniqueCandidate, candidate)) { rootBeanDefinition.setResolvedFactoryMethod(uniqueCandidate); return rootBeanDefinition.getResolvableType(); } + // Support for @Component + if (beanDefinition.getFactoryMethodName() == null && beanDefinition.getBeanClassName() != null) { + try { + return ResolvableType.forClass( + ClassUtils.forName(beanDefinition.getBeanClassName(), applicationContext.getClassLoader())); + } + catch (ClassNotFoundException ex) { + throw new IllegalArgumentException("Impossible to resolve the type of bean " + beanName, ex); + } + } throw new IllegalArgumentException("Impossible to resolve the type of bean " + beanName); } diff --git a/spring-ai-core/src/test/java/org/springframework/ai/model/function/TypeResolverHelperIT.java b/spring-ai-core/src/test/java/org/springframework/ai/model/function/TypeResolverHelperIT.java index 4b6d4ad41df..285a4f740d1 100644 --- a/spring-ai-core/src/test/java/org/springframework/ai/model/function/TypeResolverHelperIT.java +++ b/spring-ai-core/src/test/java/org/springframework/ai/model/function/TypeResolverHelperIT.java @@ -32,14 +32,14 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest -class TypeResolverHelperIT { +public class TypeResolverHelperIT { @Autowired GenericApplicationContext applicationContext; @ParameterizedTest(name = "{0} : {displayName} ") @ValueSource(strings = { "weatherClassDefinition", "weatherFunctionDefinition", "standaloneWeatherFunction", - "scannedStandaloneWeatherFunction" }) + "scannedStandaloneWeatherFunction", "componentWeatherFunction" }) void beanInputTypeResolutionWithResolvableType(String beanName) { assertThat(this.applicationContext).isNotNull(); ResolvableType functionType = TypeResolverHelper.resolveBeanType(this.applicationContext, beanName); @@ -70,7 +70,8 @@ public WeatherResponse apply(WeatherRequest weatherRequest) { } @Configuration - @ComponentScan("org.springframework.ai.model.function.config") + @ComponentScan({ "org.springframework.ai.model.function.config", + "org.springframework.ai.model.function.component" }) public static class TypeResolverHelperConfiguration { @Bean diff --git a/spring-ai-core/src/test/java/org/springframework/ai/model/function/component/ComponentWeatherFunction.java b/spring-ai-core/src/test/java/org/springframework/ai/model/function/component/ComponentWeatherFunction.java new file mode 100644 index 00000000000..704606d531f --- /dev/null +++ b/spring-ai-core/src/test/java/org/springframework/ai/model/function/component/ComponentWeatherFunction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2023-2024 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.function.component; + +import java.util.function.Function; + +import org.springframework.ai.model.function.TypeResolverHelperIT.WeatherRequest; +import org.springframework.ai.model.function.TypeResolverHelperIT.WeatherResponse; +import org.springframework.stereotype.Component; + +/** + * @author Sebastien Deleuze + */ +@Component +public class ComponentWeatherFunction implements Function { + + @Override + public WeatherResponse apply(WeatherRequest weatherRequest) { + return new WeatherResponse(42.0f); + } + +}