Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native image doesn't start and doesn't log anything if an environment post processor throws an exception #40429

Closed
danparisi opened this issue Apr 18, 2024 · 3 comments
Labels
type: bug A general bug
Milestone

Comments

@danparisi
Copy link

My spring boot 3.2.4 project doesn't start up when built native if my technical library contains an EnvironmentPostProcessor linked in spring.factories resource. If I get rid of both from the library and just copy paste the same processor in the main project repo and build it again, it works fine.

The application doesn't start either locally nor from a kubernetes POD. It just exits at startup, no logs at all are printed out:

docker --debug run --rm -p 8080 my-docker-repo:30501/repository/docker/my-service:latest
DEBU[0000] [hijack] End of stdout  

My POM looks like this:

    <parent>
        <groupId>com.xxx</groupId>
        <artifactId>my-parent</artifactId>
        <version>0.0.33</version>
    </parent>

    <artifactId>my-service<artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        ...
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.xxx</groupId>
            <artifactId>my-tech-starter</artifactId>
            <version>0.0.42-SNAPSHOT</version>
        </dependency>

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

        <dependency>
            <groupId>org.jeasy</groupId>
            <artifactId>easy-random-core</artifactId>
            <version>${easy-random.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

While my-tech-starter has a bunch of spring boot / cloud dependencies but what really makes the diff looks to be this EnvironmentPostProcessor linked in the spring.factories:

org.springframework.boot.env.EnvironmentPostProcessor=\
com.xxx.techstarter.processor.SpringConfigImportEnvironmentPostProcessor

If I removed those 2 files, it works. Even if I copy the SpringConfigImportEnvironmentPostProcessor in the main project. Note that the library is build with -Pnative flag and I can see the /META-INF/native-image/ inside the JAR.
If i do a standard, non native build, it works fine in any case.

Any idea? Thanks a lot

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 18, 2024
@scottfrederick
Copy link
Contributor

Thanks for getting in touch. Unfortunately there's not enough information here for us to understand exactly what you are doing. If you would like us to spend some time investigating, please provide a complete minimal sample that reproduces the problem. The reproducer should have the fewest dependencies possible, ideally without any Spring Cloud dependencies. You can share it with us by pushing it to a separate repository on GitHub or by zipping it and attaching it to this issue.

@scottfrederick scottfrederick added the status: waiting-for-feedback We need additional information before we can continue label Apr 18, 2024
@danparisi
Copy link
Author

Dear @scottfrederick,
Thanks for your quick reply.

I managed to create a very small example reproducing the issue:
https://github.com/danparisi/spring-boot-native-environment-post-processor-issue

Instructions about how to run it are in the README, please let me know if anything is missing.

Thanks for the support

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 19, 2024
@wilkinsona
Copy link
Member

Your environment post-processed relies on reflection through its use of SnakeYAML and you haven't provided any reachability metadata to convey that information to GraalVM. You can see the failure by wrapping the body of your postProcessEnvironment in a try-catch block:

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        try {
            …
        }
        catch (Exception ex) {
            ex.printStackTrace(System.out);
        }
    }

Running the native image will then show the failure:

Can't construct a java object for tag:yaml.org,2002:com.myservice.mytechlibrary.processor.SpringConfigImportEnvironmentPostProcessor$SpringProperties; exception=java.lang.NoSuchMethodException: com.myservice.mytechlibrary.processor.SpringConfigImportEnvironmentPostProcessor$SpringProperties.<init>()
 in 'reader', line 1, column 1:
    spring:
    ^

	at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:326)
	at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:264)
	at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:247)
	at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:201)
	at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:185)
	at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:493)
	at org.yaml.snakeyaml.Yaml.load(Yaml.java:434)
	at com.myservice.mytechlibrary.processor.SpringConfigImportEnvironmentPostProcessor.getSpringPropertiesValue(SpringConfigImportEnvironmentPostProcessor.java:75)
	at com.myservice.mytechlibrary.processor.SpringConfigImportEnvironmentPostProcessor.postProcessEnvironment(SpringConfigImportEnvironmentPostProcessor.java:39)
	at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:109)
	at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:94)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
	at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
	at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81)
	at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64)
	at java.base@21/java.lang.Iterable.forEach(Iterable.java:75)
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112)
	at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63)
	at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:369)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:329)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
	at com.myservice.myservice.Application.main(Application.java:11)
	at java.base@21/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
Caused by: org.yaml.snakeyaml.error.YAMLException: java.lang.NoSuchMethodException: com.myservice.mytechlibrary.processor.SpringConfigImportEnvironmentPostProcessor$SpringProperties.<init>()
	at org.yaml.snakeyaml.constructor.BaseConstructor.newInstance(BaseConstructor.java:382)
	at org.yaml.snakeyaml.constructor.BaseConstructor.newInstance(BaseConstructor.java:344)
	at org.yaml.snakeyaml.constructor.BaseConstructor.newInstance(BaseConstructor.java:340)
	at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructor.java:164)
	at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:320)
	... 27 more
Caused by: java.lang.NoSuchMethodException: com.myservice.mytechlibrary.processor.SpringConfigImportEnvironmentPostProcessor$SpringProperties.<init>()
	at java.base@21/java.lang.Class.checkMethod(DynamicHub.java:1065)
	at java.base@21/java.lang.Class.getConstructor0(DynamicHub.java:1228)
	at java.base@21/java.lang.Class.getDeclaredConstructor(DynamicHub.java:2930)
	at org.yaml.snakeyaml.constructor.BaseConstructor.newInstance(BaseConstructor.java:376)
	... 31 more

You need to allow instances of SpringProperties to be created using reflection.

Unfortunately, errors like this that occur before logging has been set up need to be handled carefully, particularly in a native image. We may be able to improve the diagnostics here, but I'm not certain that we can.

@wilkinsona wilkinsona changed the title Native image doesn't start if dependency library contains a EnvironmentPostProcessor in spring.factories Native image doesn't start and does not log anything if an environment post processor throws an exception Apr 19, 2024
@wilkinsona wilkinsona changed the title Native image doesn't start and does not log anything if an environment post processor throws an exception Native image doesn't start and doesn't log anything if an environment post processor throws an exception Apr 19, 2024
@wilkinsona wilkinsona added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels Apr 19, 2024
@wilkinsona wilkinsona added this to the 3.1.x milestone Apr 19, 2024
@wilkinsona wilkinsona modified the milestones: 3.1.x, 3.1.12 Apr 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants