-
Notifications
You must be signed in to change notification settings - Fork 806
Closed
Labels
Description
Describe the bug
I read that starting spring-cloud 2022.0.0, you can use native compilation. I'm using 2022.0.2 (spring-cloud-starter-openfeign:4.0.2), but when I use an OpenFeign client with native compilation, I get the following error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'boxedHelloController': Unsatisfied dependency expressed through field 'helloWorldClient': Error creating bean with name 'nl.cqit.function.poc.java.helloworld.controller.HelloWorldClient': Post-processing of FactoryBean's singleton object failed
at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveValue(AutowiredFieldValueResolver.java:195) ~[na:na]
at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveAndSet(AutowiredFieldValueResolver.java:167) ~[na:na]
at nl.cqit.function.poc.java.boxedhello.controller.BoxedHelloController__Autowiring.apply(BoxedHelloController__Autowiring.java:15) ~[na:na]
at org.springframework.beans.factory.support.InstanceSupplier$1.get(InstanceSupplier.java:83) ~[na:na]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:947) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1214) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1158) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973) ~[boxedhello-app.exe:6.0.7]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917) ~[boxedhello-app.exe:6.0.7]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[boxedhello-app.exe:6.0.7]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[boxedhello-app.exe:3.0.5]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[boxedhello-app.exe:3.0.5]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[boxedhello-app.exe:3.0.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[boxedhello-app.exe:3.0.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1304) ~[boxedhello-app.exe:3.0.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1293) ~[boxedhello-app.exe:3.0.5]
at nl.cqit.function.poc.java.boxedhello.Main.main(Main.java:12) ~[boxedhello-app.exe:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nl.cqit.function.poc.java.helloworld.controller.HelloWorldClient': Post-processing of FactoryBean's singleton object failed
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:108) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1823) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1273) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:259) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1640) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1597) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveValue(AutowiredFieldValueResolver.java:189) ~[na:na]
... 22 common frames omitted
Caused by: com.oracle.svm.core.jdk.UnsupportedFeatureError: Proxy class defined by interfaces [interface nl.cqit.function.poc.java.helloworld.controller.HelloWorldClient, interface org.springframework.aop.SpringProxy, interface org.springframework.aop.framework.Advised, interface org.springframework.core.DecoratingProxy] not found. Generating proxy classes at runtime is not supported. Proxy classes need to be defined at image build time by specifying the list of interfaces that they implement. To define proxy classes use -H:DynamicProxyConfigurationFiles=<comma-separated-config-files> and -H:DynamicProxyConfigurationResources=<comma-separated-config-resources> options.
at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89) ~[na:na]
at org.graalvm.nativeimage.builder/com.oracle.svm.core.reflect.proxy.DynamicProxySupport.getProxyClass(DynamicProxySupport.java:171) ~[na:na]
at java.base@19.0.2/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:47) ~[boxedhello-app.exe:na]
at java.base@19.0.2/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1037) ~[boxedhello-app.exe:na]
at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:123) ~[na:na]
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110) ~[na:na]
at org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor.postProcessAfterInitialization(AbstractAdvisingBeanPostProcessor.java:127) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:434) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1885) ~[boxedhello-app.exe:6.0.7]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:105) ~[boxedhello-app.exe:6.0.7]
... 32 common frames omitted
Sample
Here is my API:
package nl.cqit.function.poc.java.helloworld.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import nl.cqit.function.poc.java.helloworld.api.model.Person;
import nl.cqit.function.poc.java.helloworld.api.model.Problem;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
@Validated
@Tag(
name = "HelloWorld",
description = "the HelloWorld API"
)
public interface HelloWorldApi {
@Operation(
operationId = "sayHello",
summary = "The main function",
description = "This endpoint will call sayHello",
tags = {"HelloWorld"},
responses = {@ApiResponse(
responseCode = "200",
description = "OK",
content = {@Content(
mediaType = "application/json",
schema = @Schema(
implementation = String.class
)
), @Content(
mediaType = "application/problem+json",
schema = @Schema(
implementation = String.class
)
)}
), @ApiResponse(
responseCode = "400",
description = "input validation failed",
content = {@Content(
mediaType = "application/json",
schema = @Schema(
implementation = Problem.class
)
), @Content(
mediaType = "application/problem+json",
schema = @Schema(
implementation = Problem.class
)
)}
)}
)
@RequestMapping(
method = {RequestMethod.POST},
value = {"/helloWorld"},
produces = {"application/json", "application/problem+json"},
consumes = {"application/json"}
)
@ResponseStatus(HttpStatus.OK)
String sayHello(@Parameter(name = "Person",description = "",required = true) @RequestBody @Valid Person var1);
}
And here is my Feign client:
package nl.cqit.function.poc.java.helloworld.controller;
import nl.cqit.function.poc.java.helloworld.api.HelloWorldApi;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name = "helloWorldClient", url = "http://localhost:8080")
public interface HelloWorldClient extends HelloWorldApi {
}
I'm using it like this:
package nl.cqit.function.poc.java.boxedhello.impl;
import nl.cqit.function.poc.java.boxedhello.api.BoxedHelloApi;
import nl.cqit.function.poc.java.boxedhello.api.model.Person;
import nl.cqit.function.poc.java.helloworld.controller.HelloWorldClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BoxedHelloImpl implements BoxedHelloApi {
@Autowired
private HelloWorldClient helloWorldClient;
@Override
public String sayHello(Person person) {
String greeting = helloWorldClient.sayHello(map(person));
String horizontalEdge = "+" + "-".repeat(greeting.length() + 2) + "+";
return horizontalEdge + "\n| " + greeting + " |\n" + horizontalEdge;
}
private nl.cqit.function.poc.java.helloworld.api.model.Person map(Person person) {
return new nl.cqit.function.poc.java.helloworld.api.model
.Person(person.getFirstName())
.lastName(person.getLastName());
}
}
With this as my Main class:
package nl.cqit.function.poc.java.boxedhello;
import nl.cqit.function.poc.java.helloworld.controller.HelloWorldClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients(basePackageClasses = {HelloWorldClient.class})
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Using this profile for native compilation in my pom.xml:
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
</env>
</image>
</configuration>
<executions>
<execution>
<id>process-aot</id>
<goals>
<goal>process-aot</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<metadataRepository>
<enabled>true</enabled>
</metadataRepository>
<requiredVersion>22.3</requiredVersion>
</configuration>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
</execution>
<execution>
<id>add-reachability-metadata</id>
<goals>
<goal>add-reachability-metadata</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Is this a bug or am I missing something?