spring-attic / spring-native

Spring Native is now superseded by Spring Boot 3 official native support
https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html
Apache License 2.0
2.74k stars 355 forks source link

Fail to run application that use a feignClient (native or aot jar run) #1661

Closed mpumd closed 2 years ago

mpumd commented 2 years ago

Hi everyone,

I tried to compile and run some applications that use the feign client.

My configuration is the following :

Compile is ok after add a trick like --initialize-at-build-time=sun.instrument.InstrumentationImpl. I combine the tracing agent results with the spring aot plugin. But during the run, spring boot fail to start in native image mode or spring Aot mode -DspringAot=true

So I confirmed my issue in a POC which gave me this following log :

java -DspringAot=true -jar target/native-feign-client-0.0.1-SNAPSHOT.jar


2022-07-06 10:52:55.804  INFO 23072 --- [           main] o.s.nativex.NativeListener               : AOT mode enabled

. _ _ /\ / '_ () \ \ \ \ ( ( )\ | ' | '| | ' \/ ` | \ \ \ \ \/ _)| |)| | | | | || (| | ) ) ) ) ' |__| .|| ||| |\, | / / / / =========|_|==============|__/=//// :: Spring Boot :: (v2.7.1)

2022-07-06 10:52:56.112 INFO 23072 --- [ main] c.l.n.f.NativeFeignClientApplication : Starting NativeFeignClientApplication v0.0.1-SNAPSHOT using Java 11.0.15 on DEVPC026599 with PID 2307 2 (E:\git\poc\native-feign-client\native-feign-client\target\native-feign-client-0.0.1-SNAPSHOT.jar started by mpusg in E:\git\poc\native-feign-client\native-feign-client) 2022-07-06 10:52:56.112 INFO 23072 --- [ main] c.l.n.f.NativeFeignClientApplication : No active profile set, falling back to 1 default profile: "default" 2022-07-06 10:52:57.034 INFO 23072 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http) 2022-07-06 10:52:57.049 INFO 23072 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2022-07-06 10:52:57.049 INFO 23072 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.64] 2022-07-06 10:52:57.199 INFO 23072 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2022-07-06 10:52:57.199 INFO 23072 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1087 ms 2022-07-06 10:52:57.565 WARN 23072 --- [ main] w.s.c.ServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework .beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'controller': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans .factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.exa.nativetest.feign.FeignClientPublicApi' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} 2022-07-06 10:52:57.580 INFO 23072 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] 2022-07-06 10:52:57.627 ERROR 23072 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :


APPLICATION FAILED TO START


Description:

Parameter 0 of constructor in com.exa.nativetest.feign.Controller required a bean of type 'com.exa.nativetest.feign.FeignClientPublicApi' that could not be found.

Action:

Consider defining a bean of type 'com.exa.nativetest.feign.FeignClientPublicApi' in your configuration.


During the compilation of the aot plugin, I saw this following log : 

2022-07-06 09:03:25.789 ERROR 6848 --- [ main] s.a.c.b.g.ApplicationContextAotProcessor : Failed to handle bean com.exa.nativetest.feign.FeignClientPublicApi with definition Root bean: class [com.exa.nativetest.feign.FeignClientPublicApi]; scope=singleton; abstract=false; lazyInit=true; autowireMode=2; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=null; factoryMe thodName=null; initMethodName=null; destroyMethodName=null


Feign client don't seems to be supported by the aot plugin.

```java
@RestController
@AllArgsConstructor
public class Controller {

    private final FeignClientPublicApi client;

    @GetMapping("/test")
    @ResponseStatus(HttpStatus.OK)
    public String test() {
        return client.retrieveBooks();
    }
}
@FeignClient(value = "public-client-api", url = "http://openlibrary.org/api/books")
public interface FeignClientPublicApi {

    @GetMapping("?bibkeys=ISBN:0201558025,LCCN:93005405")
    String retrieveBooks();
}
@SpringBootApplication
@EnableFeignClients
public class NativeFeignClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(NativeFeignClientApplication.class, args);
    }
}
<?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>2.7.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.exa.native</groupId>
    <artifactId>native-feign-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>native-feign-client</name>
    <description>native-feign-client</description>

    <properties>
        <java.version>11</java.version>
        <spring-cloud.version>2021.0.3</spring-cloud.version>
        <spring-native.version>0.12.0</spring-native.version>
        <!-- Fix an issue in 2.22.2 with Junit 5 : https://issues.apache.org/jira/browse/SUREFIRE-1679, wait for 2.22.3 -->
        <maven-surefire-plugin.version>3.0.0-M7</maven-surefire-plugin.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.experimental</groupId>
                <artifactId>spring-native</artifactId>
                <version>${spring-native.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.experimental</groupId>
            <artifactId>spring-native</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>tracingAgent</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.experimental</groupId>
                        <artifactId>spring-aot-maven-plugin</artifactId>
                        <version>${spring-native.version}</version>
                        <configuration>
                            <mode>native-agent</mode>
                            <debugVerify>true</debugVerify>
                        </configuration>
                    </plugin>
                    <plugin>
                        <!-- FIXME be careful of jacoco config -->
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <configuration>
                            <!-- output dir -->
                            <!-- <argLine>-agentlib:native-image-agent=access-filter-file=access-filter.json,config-output-dir=target/classes/META-INF/native-image</argLine>-->
                            <!-- merge dir -->
                            <argLine>
                                -agentlib:native-image-agent=access-filter-file=access-filter.json,config-merge-dir=target/classes/META-INF/native-image
                            </argLine>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>aotCompile</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.experimental</groupId>
                        <artifactId>spring-aot-maven-plugin</artifactId>
                        <version>${spring-native.version}</version>
                        <configuration>
                            <debugVerify>true</debugVerify>
                        </configuration>
                        <executions>
                            <execution>
                                <id>generate</id>
                                <goals>
                                    <goal>generate</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>nativeImage</id>
            <properties>
                <paketo.builder.image>tiny</paketo.builder.image> <!-- full, base, tiny -->
                <repackage.classifier/>
                <native.image.build.arguments/>
                <enable-apm>false</enable-apm>
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-dependency-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>unpack</id>
                                <phase>generate-sources</phase>
                                <goals>
                                    <goal>unpack</goal>
                                </goals>
                                <configuration>
                                    <artifactItems>
                                        <artifactItem>
                                            <groupId>com.lodh.arte</groupId>
                                            <artifactId>buildpack-bindings</artifactId>
                                            <version>1.0.0</version>
                                            <type>zip</type>
                                        </artifactItem>
                                    </artifactItems>
                                    <outputDirectory>${project.build.directory}</outputDirectory>
                                    <overWriteReleases>false</overWriteReleases>
                                    <overWriteSnapshots>true</overWriteSnapshots>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <configuration>
                            <classifier>${repackage.classifier}</classifier>
                            <image>
                                <builder>paketobuildpacks/builder:${paketo.builder.image}</builder>
                                <env>
                                    <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
                                    <BP_NATIVE_IMAGE_BUILD_ARGUMENTS>${native.image.build.arguments}
                                    </BP_NATIVE_IMAGE_BUILD_ARGUMENTS>
                                    <BP_JVM_VERSION>${java.version}</BP_JVM_VERSION>
                                    <BP_IMAGE_LABELS>name="${native.image.name}"</BP_IMAGE_LABELS>
                                    <BPE_TZ>Europe/Zurich</BPE_TZ>
                                    <BPE_CHARSET>UTF-8</BPE_CHARSET>
                                    <BPE_LANGUAGE>fr_CH.UTF-8</BPE_LANGUAGE>
                                    <BPE_LANG>fr_CH.UTF-8</BPE_LANG>
                                    <BPE_LC_ALL>fr_CH.UTF-8</BPE_LC_ALL>
                                </env>
                                <bindings>
                                    <binding>
                                        ${project.build.directory}/bindings/ca-certificates:/platform/bindings/ca-certificates
                                    </binding>
                                </bindings>
                            </image>
                        </configuration>
                    </plugin>
                </plugins>
            </build>

            <!-- Repositories temporarily required for spring-native artifacts -->
            <repositories>
                <repository>
                    <id>spring-releases</id>
                    <name>Spring Releases</name>
                    <url>https://repo.spring.io/release</url>
                    <snapshots>
                        <enabled>false</enabled>
                    </snapshots>
                </repository>
            </repositories>
            <pluginRepositories>
                <pluginRepository>
                    <id>spring-releases</id>
                    <name>Spring Releases</name>
                    <url>https://repo.spring.io/release</url>
                    <snapshots>
                        <enabled>false</enabled>
                    </snapshots>
                </pluginRepository>
            </pluginRepositories>
        </profile>
    </profiles>
</project>

Any idea ? Thanks

mhalbritter commented 2 years ago

If you'd like us to spend some time investigating, please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.

mpumd commented 2 years ago

Hi mhalbritter,

Sorry for the lack of information. My simple test project is available on the following zip.

I build and run it with the following commands :

mvn clean test -PtracingAgent && mvn package -DskipTests -PaotCompile && mvn spring-boot:build-image -DskipTests -PnativeImage

docker run --rm -p 8081:8081 native-feign-client:0.0.1-SNAPSHOT

native-feign-client.zip

Thanks for your time.

lgklein commented 2 years ago

I think this is the same as https://github.com/spring-projects-experimental/spring-native/issues/766... You need to downgrade to 0.10.6 and use as it is describe there.

mhalbritter commented 2 years ago

Yes, like @lgklein said, this is not supported on 0.12.0. We're working on supporting that with Spring Boot 3.x and Spring Framework 6.x.