AOT failed with 'className cannot be null' - Spring Cloud version: 2022.0.0 - Spring Boot version: 3.0.1 - Java version: jdk17 - Spring Cloud Alibaba version: 2022.0.0.0-RC1
Exception
Exception in thread "main" java.lang.IllegalArgumentException: className cannot be null
at org.springframework.util.Assert.notNull(Assert.java:204)
at org.springframework.cloud.openfeign.aot.FeignClientBeanFactoryInitializationAotProcessor$AotContribution.lambda$applyTo$1(FeignClientBeanFactoryInitializationAotProcessor.java:117)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1779)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.springframework.cloud.openfeign.aot.FeignClientBeanFactoryInitializationAotProcessor$AotContribution.applyTo(FeignClientBeanFactoryInitializationAotProcessor.java:124)
at org.springframework.context.aot.BeanFactoryInitializationAotContributions.applyTo(BeanFactoryInitializationAotContributions.java:78)
at org.springframework.context.aot.ApplicationContextAotGenerator.lambda$processAheadOfTime$0(ApplicationContextAotGenerator.java:58)
at org.springframework.context.aot.ApplicationContextAotGenerator.withCglibClassHandler(ApplicationContextAotGenerator.java:67)
at org.springframework.context.aot.ApplicationContextAotGenerator.processAheadOfTime(ApplicationContextAotGenerator.java:53)
at org.springframework.context.aot.ContextAotProcessor.performAotProcessing(ContextAotProcessor.java:106)
at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:84)
at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:49)
at org.springframework.context.aot.AbstractAotProcessor.process(AbstractAotProcessor.java:82)
at org.springframework.boot.SpringApplicationAotProcessor.main(SpringApplicationAotProcessor.java:76)
Feign Client
/**
* 用户接口。
*
* @author Ben
* @version 1.0.0
* @since 2022/12/28
*/
@FeignClient(
name = "springcloud-service-manager",
contextId = "userFeignService",
path = "/user",
fallbackFactory = UserService.UserServiceFallbackFactory.class)
public interface UserService {
/**
* 获取当前用户信息。
* @return 当前用户信息。
*/
@GetMapping("/me")
User me();
/**
* 根据请求令牌获取用户信息。
* @param accessToken 请求令牌。
* @return 用户信息。
*/
@GetMapping("/whoami")
User whoami(@RequestParam String accessToken);
/**
* 新增用户。
* @param user 用户对象。
* @return 保存成功的用户对象。
*/
@PostMapping
User add(@RequestBody User user);
/**
* 删除用户。
* @param id 用户ID。
*/
@DeleteMapping("/{id}")
void delete(@PathVariable Long id);
/**
* 更新用户。
* @param id 用户ID。
* @param user 用户信息。
* @return 用户存在时返回更新后的对象,否则返回 {@literal null} 。
*/
@PutMapping("/{id}")
User update(@PathVariable Long id, @RequestBody User user);
/**
* 修改密码。
* @param id 用户ID。
* @param oldPassword 当前密码。
* @param newPassword 新密码。
*/
@PutMapping("/{id}/password")
void changePassword(@PathVariable Long id, @RequestParam String oldPassword, @RequestParam String newPassword);
/**
* 获取用户。
* @param id 用户ID。
* @return 用户存在时返回对象,否则返回 {@literal null} 。
*/
@GetMapping("/{id}")
User get(@PathVariable Long id);
/**
* 根据用户名获取用户。
* @param username 用户名。
* @return 用户存在时返回对象,否则返回 {@literal null} 。
*/
@GetMapping("/username/{username}")
User getByUsername(@PathVariable String username);
/**
* 统计用户数。
* @param condition 查询条件。
* @return 符合条件的用户数。
*/
@GetMapping("/count")
long count(@SpringQueryMap UserCondition condition);
/**
* 查询用户列表。
* @param condition 查询条件。
* @param sort 排序规则。
* @return 用户列表。
*/
@GetMapping("/list")
List<User> getList(@SpringQueryMap UserCondition condition, Sort sort);
/**
* 查询用户分页数据。
* @param condition 查询条件。
* @param pageable 分页信息。
* @return 用户分页数据。
*/
@GetMapping("/page")
Page<User> getPage(@SpringQueryMap UserCondition condition, Pageable pageable);
/**
* 获取 <code>status</code> 属性选项。
* @return 选项列表。
*/
@GetMapping("/status/options")
List<Map<Object, Object>> getStatusOptions();
@Component
@Slf4j
class UserServiceFallbackFactory implements FallbackFactory<UserService> {
@Override
public UserService create(Throwable cause) {
return new UserService() {
@Override
public User me() {
log.error("服务熔断", cause);
return null;
}
@Override
public User whoami(String accessToken) {
log.error("服务熔断: accessToken={}", accessToken, cause);
return null;
}
@Override
public User add(User user) {
log.error("服务熔断: user={}", user, cause);
return null;
}
@Override
public void delete(Long id) {
log.error("服务熔断: id={}", id, cause);
}
@Override
public User update(Long id, User user) {
log.error("服务熔断: id={},user={}", id, user, cause);
return null;
}
@Override
public void changePassword(Long id, String oldPassword, String newPassword) {
log.error("服务熔断: id={},oldPassword={},newPassword={}", id, oldPassword, newPassword, cause);
}
@Override
public User get(Long id) {
log.error("服务熔断: id={}", id, cause);
return null;
}
@Override
public User getByUsername(String username) {
log.error("服务熔断: username={}", username, cause);
return null;
}
@Override
public long count(UserCondition condition) {
log.error("服务熔断: condition={}", condition, cause);
return 0;
}
@Override
public List<User> getList(UserCondition condition, Sort sort) {
log.error("服务熔断: condition={},sort={}", condition, sort, cause);
return List.of();
}
@Override
public Page<User> getPage(UserCondition condition, Pageable pageable) {
log.error("服务熔断: condition={},pageable={}", condition, pageable, cause);
return new PageImpl<>(List.of(), pageable, 0L);
}
@Override
public List<Map<Object, Object>> getStatusOptions() {
log.error("服务熔断", cause);
return List.of();
}
};
}
}
}
Code Position
@Override
public void applyTo(GenerationContext generationContext,
BeanFactoryInitializationCode beanFactoryInitializationCode) {
ProxyHints proxyHints = generationContext.getRuntimeHints().proxies();
Set<String> feignClientRegistrationMethods = feignClientBeanDefinitions.values().stream()
.map(beanDefinition -> {
Assert.notNull(beanDefinition, "beanDefinition cannot be null");
Assert.isInstanceOf(GenericBeanDefinition.class, beanDefinition);
GenericBeanDefinition registeredBeanDefinition = (GenericBeanDefinition) beanDefinition;
MutablePropertyValues feignClientProperties = registeredBeanDefinition.getPropertyValues();
String className = (String) feignClientProperties.get("type");
Assert.notNull(className, "className cannot be null");
My pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.stark.springcloud</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>springcloud-auth-server</artifactId>
<properties>
<spring-boot.build-image.imageName>192.168.41.24/spring-cloud-alibaba/${project.artifactId}:${project.version}</spring-boot.build-image.imageName>
</properties>
<dependencies>
<!-- spring-authorization-server start -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- spring-authorization-server end -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!-- openfeign start -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<!-- openfeign end -->
<!-- sentinel start -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- sentinel end -->
<dependency>
<groupId>com.stark.springcloud</groupId>
<artifactId>springcloud-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
My application.yml
spring:
application:
name: springcloud-auth-server
profiles:
active: dev
cloud:
refresh:
enabled: false
openfeign:
client:
refresh-enabled: false
lazy-attributes-resolution: false
Maven command
mvn clean -Pnative spring-boot:build-image
Comment From: OlgaMaciaszek
Hello @benfromchina, please provide a minimal, complete, verifiable example that reproduces the issue, as a link to a repo with a small executable app instead of separate code fragments.
Comment From: spring-cloud-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-cloud-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.