I have built a native image with SpringBoot 3.0 and native-maven-plugin. It package successed but started failed because of throwing ConverterNotFoundException. I ran the jar, it started successfully.

Spring Boot version: 3.0.3

Error Log:

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'auth.login.request-method' to org.springframework.http.HttpMethod:

    Reason: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [org.springframework.http.HttpMethod]

Action:

Update your application's configuration

The properties class:

@Configuration
@ConfigurationProperties(prefix = "auth")
@Validated
@Getter
@Setter
public class BusinessProperties {

    private Login login;

    @Getter
    @Setter
    public static class Login {

        @NotBlank()
        private String requestPath;

        @NotNull()
        private HttpMethod requestMethod;
    }
}

The yaml properties:

auth:
  login:
    request-method: POST
    request-path: /login

Comment From: wilkinsona

I guess that HttpMethod is Spring Framework's org.springframework.http.HttpMethod in which case I suspect that this is failing due to a lack of reflection metadata for its valueOf(String) method. To remove the need for guesswork, please provide a complete yet minimal sample that reproduces the problem. You can share such a sample with us by zipping it up and attaching it to this issue or by pushing it to a separate repository on GitHub. Judging by the code snippets above, you appear to be using Lombok. If the problem occurs without Lombok, please do not use it in the sample as its inclusion adds unnecessary complexity and makes problem diagnosis more difficult.

Comment From: human-user

@wilkinsona Thank you for response. Here is the sample: demo.zip

Comment From: wilkinsona

Thanks for the minimal sample, it's confirmed the guesses that I made above. You can avoid the problem by allowing reflective calls to HttpMethod.valueOf(String). One way to do that is with some runtime hints:

package com.example.demo;

import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.http.HttpMethod;

import com.example.demo.DemoApplication.HttpMethodConversionRuntimeHints;

@SpringBootApplication
@ImportRuntimeHints(HttpMethodConversionRuntimeHints.class)
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    static class HttpMethodConversionRuntimeHints implements RuntimeHintsRegistrar {

        @Override
        public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
            hints.reflection().registerType(HttpMethod.class, MemberCategory.INVOKE_PUBLIC_METHODS);
        }

    }

}

It would be good if this wasn't necessary as the required hints were automatically generated at build time. However, I am not sure that this is possible as it would require build-time determination of the converter that will be used to bind your auth.login.request-method property. I'll leave the issue open for now as I'd like to discuss it with the team to see what might be possible.

/cc @sdeleuze

Comment From: sdeleuze

ObjectToObjectConverter is one of the few areas where the behavior is so dynamic in term of reflection that there is no obvious perfect solution and where we need to decide on a case by case basis if the use case is popular enough to be supported out of the box for native or if we require explicit hints from users.

Via spring-projects/spring-framework#29429, we introduced an ObjectToObjectConverterRuntimeHints used for date/time conversion, where we could potentially add such reflective hint for HttpMethod.valueOf(String) if you think that's a common use case. Otherwise, the recommandation is to configure that explicitly on application side as suggested above.

Comment From: human-user

@sdeleuze I think many libs or projects use HttpMethod in configuration properties such like https://github.com/spring-cloud/spring-cloud-gateway/issues/2876. To avoid those issues, it's better to add the hint to ObjectToObjectConverterRuntimeHints.

Comment From: sdeleuze

Could make sense from my POV.

@wilkinsona Please let me know if you agree, and if you do, if you want to move this issue on Framework side or if a new issue should be created.

Comment From: wilkinsona

I think it's hard to tell how common it is. FWIW, this issue's the first time that I've seen the problem and Gateway could, of course, provide its own metadata. I wouldn't oppose a change in Framework that's specific for HttpMethod. I think a separate issue for that would be best as I'd like to keep this issue open in the Boot tracker at least until we've had a chance to discuss it as a team.

I do wonder if there's something better that we could do in the longer term. I'm imagining some build-time processing that builds on what we already know about configuration properties and extends it to also consider type conversion. This would almost certainly require API changes as I think Converter implementations would have to somehow opt in to providing reflection hints, answering the question "if you converted this type, what reflection hints would you need to be able to do so?".

Comment From: snicoll

I've created https://github.com/spring-projects/spring-framework/issues/30722 to explore the idea of extending the conversion contract to be AOT aware. If that comes to a conclusion, we'll adapt as Andy explained above. I am going to close this now as there's nothing actionable at this time and the original issue with HttpMethod has been fixed in the meantime.