spring-cloud / spring-cloud-function

Apache License 2.0
1.03k stars 614 forks source link

4.1.3 GCP Adapter - GcfJarLauncher: Failed to lookup function #1164

Open gfourny-sfeir opened 1 month ago

gfourny-sfeir commented 1 month ago

Describe the bug We have still bug on spring-cloud-function-adapter-gcp 4.1.3. We using Spring Boot 3.3.1 with Spring Cloud Function. When the function is invoking, we have this error:

Failed to execute org.springframework.cloud.function.adapter.gcp.GcfJarLauncher java.lang.IllegalArgumentException: Failed to lookup function to route based on the value of 'spring.cloud.function.definition' property 'generateAvatar'

It was working with Spring Boot 3.1.x

Sample pom.xml:

    <properties>
        <java.version>17</java.version>
        <spring-boot.version>3.3.1</spring-boot.version>
        <spring-cloud.version>2023.0.3</spring-cloud.version>
        <function-maven-plugin.version>0.11.0</function-maven-plugin.version>
        <spring-boot-maven-plugin.version>3.3.1</spring-boot-maven-plugin.version>
        <spring-cloud-function-adapter-gcp.version>4.1.3</spring-cloud-function-adapter-gcp.version>
    </properties>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-context</artifactId>
        </dependency>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- Adapteur GCP -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-adapter-gcp</artifactId>
        </dependency>
        <!-- Cloud Function Web HTTP-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-function-web</artifactId>
        </dependency>

    <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <outputDirectory>target/deploy</outputDirectory>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-function-adapter-gcp</artifactId>
                        <version>${spring-cloud-function-adapter-gcp.version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>build-info</goal>
                            <goal>repackage</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${basedir}/package</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
        </plugin>

The java Bean :

    @Bean
    Supplier<AvatarResponse> generateAvatar() {
        return avatarGenerator::generate;
    }

The properties:

spring:
  application:
    name: vod-profil-avatar
  cloud:
    function:
      definition: generateAvatar

I have two integration tests to validate the function, all passed:

    @Autowired
    private TestRestTemplate rest;
    @Autowired
    private Storage storage;
    @Value("${u-cf.bucket-name}")
    private String bucketName;
    @Autowired
    private FunctionCatalog functionCatalog;

    @DisplayName("Doit générer un avatar")
    @Test
    void should_generate_avatar() {
        //Given 🔨

        //When 👉
        ResponseEntity<AvatarResponse> avatarResponse = this.rest.getForEntity(URI.create("/"), AvatarResponse.class);

        //then ✅
        assertThat(avatarResponse).isNotNull()
                .satisfies(response -> response.getStatusCode().is2xxSuccessful())
                .extracting(ResponseEntity::getBody)
                .isNotNull()
                .satisfies(input -> {
                    var blob = storage.get(bucketName, input.blobId());
                    assertThat(blob).isNotNull();
                });
    }

    @DisplayName("Doit générer un avatar")
    @Test
    void should_generate_avatar_catalog() {
        //Given 🔨
        Supplier<AvatarResponse> generateAvatar = functionCatalog.lookup(Supplier.class, "generateAvatar");

        //When 👉
        AvatarResponse avatar = generateAvatar.get();

        //Then ✅
        assertThat(avatar)
                .isNotNull()
                .satisfies(input -> {
                    var blob = storage.get(bucketName, input.blobId());
                    assertThat(blob).isNotNull();
                });

    }
gfourny-sfeir commented 1 month ago

On invocation, the beans of our application aren't scanned. However, locally with the function plugin, we saw all beans. To show this, the config of logback-spring.xml:

<logger name="org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLogger" level="DEBUG" additivity="false">
    <appender-ref ref="consoleAppender"/>
</logger>
<logger name="org.springframework.context.annotation.ClassPathBeanDefinitionScanner" level="DEBUG" additivity="false">
    <appender-ref ref="consoleAppender"/>
</logger>
<logger name="org.springframework.beans.factory.support.DefaultListableBeanFactory" level="DEBUG" additivity="false">
    <appender-ref ref="consoleAppender"/>
</logger>