Small question regarding the new Spring Boot 3 with AOT/native/GraalVM please
Lately, many talks regarding the new Spring Boot 3 are about the AOT/native/GraalVM.
I went to try migrating a project which was building without GraalVM, to this new paradigm so many are talking about.
Here is the straightforward code of the project:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
public class ElasticController {
private final ElasticRepository elasticRepository;
@Autowired
public ElasticController(ElasticRepository elasticRepository) {
this.elasticRepository = elasticRepository;
}
@PostMapping(path = "/save", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<String> save(@RequestBody ElasticPojo elasticPojo) {
return elasticRepository.save(elasticPojo).map(__ -> "with graalVM, is is not working");
}
}
package com.example.demo;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ElasticRepository extends ReactiveCrudRepository<ElasticPojo, String> {
}
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration;
import java.time.Duration;
@Configuration
public class ElasticConfiguration extends ReactiveElasticsearchConfiguration {
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder().connectedTo("localhost:9200").withConnectTimeout(Duration.ofMinutes(2L)).withSocketTimeout(Duration.ofMinutes(2L)).build();
}
}
package com.example.demo;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
@Document(indexName = "question")
public class ElasticPojo {
@Id
private String id;
private String link;
public ElasticPojo(String id, String link) {
this.id = id;
this.link = link;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
@Override
public String toString() {
return "ElasticPojo{" +
"id='" + id + '\'' +
", link='" + link + '\'' +
'}';
}
}
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The GraalVM version is: graalvm-ce-java17-22.3.0
While running mvnw.cmd -Pnative native:compile
the project builds fine, running the native image always yields this error:
target\demo.exe
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.1)
2023-01-02T20:42:09.935+08:00 INFO 2860 --- [ main] com.example.demo.DemoApplication : Starting AOT-processed DemoApplication using Java 17.0.5 with PID 2860 (C:\Users\...\demo\target\demo.exe started by xxxin ...\demo)
2023-01-02T20:42:09.935+08:00 INFO 2860 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default"
2023-01-02T20:42:09.991+08:00 WARN 2860 --- [ main] .r.c.ReactiveWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'elasticController': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'elasticRepository': Cannot resolve reference to bean 'reactiveElasticsearchTemplate' while setting bean property 'reactiveElasticsearchOperations'
2023-01-02T20:42:10.005+08:00 ERROR 2860 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'elasticController': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'elasticRepository': Cannot resolve reference to bean 'reactiveElasticsearchTemplate' while setting bean property 'reactiveElasticsearchOperations'
at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:351) ~[na:na]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:271) ~[na:na]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:206) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1225) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1210) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1157) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:961) ~[demo.exe:6.0.3]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:915) ~[demo.exe:6.0.3]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[demo.exe:6.0.3]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[demo.exe:3.0.1]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[demo.exe:3.0.1]
at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[demo.exe:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticRepository': Cannot resolve reference to bean 'reactiveElasticsearchTemplate' while setting bean property 'reactiveElasticsearchOperations'
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:377) ~[na:na]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:135) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1663) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1412) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1405) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:334) ~[na:na]
... 21 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reactiveElasticsearchOperations': Instantiation of supplied bean failed
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1236) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1210) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1157) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:365) ~[na:na]
... 34 common frames omitted
Caused by: java.lang.ExceptionInInitializerError: null
at org.springframework.data.elasticsearch.core.AbstractReactiveElasticsearchTemplate.<init>(AbstractReactiveElasticsearchTemplate.java:93) ~[demo.exe:5.0.0]
at org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchTemplate.<init>(ReactiveElasticsearchTemplate.java:84) ~[na:na]
at org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration.reactiveElasticsearchOperations(ReactiveElasticsearchConfiguration.java:84) ~[demo.exe:5.0.0]
at com.example.demo.ElasticConfiguration$$SpringCGLIB$$0.CGLIB$reactiveElasticsearchOperations$3(<generated>) ~[demo.exe:na]
at com.example.demo.ElasticConfiguration$$SpringCGLIB$$1.invoke(<generated>) ~[demo.exe:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) ~[demo.exe:6.0.3]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[na:na]
at com.example.demo.ElasticConfiguration$$SpringCGLIB$$0.reactiveElasticsearchOperations(<generated>) ~[demo.exe:na]
at org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration__BeanDefinitions.lambda$getReactiveElasticsearchOperationsInstanceSupplier$2(ReactiveElasticsearchConfiguration__BeanDefinitions.java:61) ~[na:na]
at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:68) ~[demo.exe:6.0.3]
at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:54) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.lambda$get$2(BeanInstanceSupplier.java:208) ~[na:na]
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:59) ~[demo.exe:6.0.3]
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:47) ~[demo.exe:6.0.3]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.invokeBeanSupplier(BeanInstanceSupplier.java:220) ~[na:na]
at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:208) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1225) ~[demo.exe:6.0.3]
... 43 common frames omitted
Caused by: java.lang.IllegalStateException: Resource not found
at org.springframework.data.elasticsearch.support.VersionInfo.loadVersionProperties(VersionInfo.java:108) ~[na:na]
at org.springframework.data.elasticsearch.support.VersionInfo.<clinit>(VersionInfo.java:51) ~[na:na]
... 60 common frames omitted
To avoid confusion, I am building and running fine the same code with openJDK, and any other JDK. Actually, even with GraalVM, but not using the native, it compiles and runs fine.
Only when compiling native, and running native, the issue occurs, 100% of the time.
May I ask what am I doing wrong please?
Thank you
In the non-native variant we'll get an IOException
when the resource is missing and ignore that. But the native application throws an IllegalStateException
.
Thanks for creating this issue . I am currently working on it. It's not only the version.properties
but some other options that need to be set in the RuntimeHintsRegistrar
. Should be done in the next days.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.