After upgrading from 2.7.11 to 3.0.7 system environment isn't applied to Property

I have a property 'home' in Globals class https://github.com/sergmain/metaheuristic/blob/5f660e45baf44720996cf5f385e26ad99a1a9eb5/apps/metaheuristic/src/main/java/ai/metaheuristic/ai/Globals.java#L528

In 2.7.11 initializing OS environment MH_HOME was enough to set Globals.home to a new value.

after upgrading to 3.0.7 Globals.home isn't initialized

Caused by: java.lang.IllegalArgumentException: mh.home isn't specified
at ai.metaheuristic.ai.Globals.getHome(Globals.java:532) ~[classes/:na]
at ai.metaheuristic.ai.Globals.postConstruct(Globals.java:549) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:425) ~[spring-beans-6.0.9.jar:6.0.9]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:369) ~[spring-beans-6.0.9.jar:6.0.9]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:193) ~[spring-beans-6.0.9.jar:6.0.9]
... 123 common frames omitted

Comment From: sergmain

Addition. I don't know, do I need to create a new bug or don't, so I post here

Order of @PostConstruct is completely broken I have a service MetadataService which has an autowired bean EnvService

PostConstruct of MetadataService is being called before PostConstruct of EnvService

https://github.com/sergmain/metaheuristic/blob/5f660e45baf44720996cf5f385e26ad99a1a9eb5/apps/metaheuristic/src/main/java/ai/metaheuristic/ai/processor/MetadataService.java#L72

Comment From: mhalbritter

Hey, I can't reproduce that issue. My test application works fine. When setting MH_HOME=test it prints test.

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.

For your second comment: If you think there's a bug, please create a separate issue.

Comment From: wilkinsona

For your second comment: If you think there's a bug, please create a separate issue.

If you open an issue, it should be a Spring Framework issue as it handles @PostConstruct. It should also be accompanied by a minimal sample.

Comment From: sergmain

Hey, I can't reproduce that issue. My test application works fine. When setting MH_HOME=test it prints test.

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.

For your second comment: If you think there's a bug, please create a separate issue.

I managed to reproduce a bug with your code - adding private final Environment env; to TestAppProperties is enough reproduce https://github.com/sergmain/sb-35718/blob/98d460ac2a987c097da22f6fbe94b674224caa4b/src/main/java/com/example/sb35718/TestAppProperties.java#L15

After adding this line method org.springframework.boot.context.properties.ConfigurationPropertiesBean.BindMethod#get(java.lang.Class<?>) return VALUE_OBJECT instead of JAVA_BEAN

Comment From: mhalbritter

Yes, because the binder is now using constructor based binding. If you do this, it works again:

    private final Path home;

    private final Environment environment;

    public TestAppProperties(Path home, Environment environment) {
        this.home = home;
        this.environment = environment;
    }

    public Path getHome() {
        return this.home;
    }

But injecting Environment into @ConfigurationProperties doesn't work.

Comment From: sergmain

That would be nice to have ISE or at least message in log that @ConfigurationProperties is being used in wrong way.

Comment From: wilkinsona

Unfortunately, I don't think we can tell with absolute certainty that a particular arrangement is wrong.

FWIW, the documentation does provide some advice with which your Globals class is not aligned:

We recommend that @ConfigurationProperties only deal with the environment and, in particular, does not inject other beans from the context. For corner cases, setter injection can be used or any of the *Aware interfaces provided by the framework (such as EnvironmentAware if you need access to the Environment). If you still want to inject other beans using the constructor, the configuration properties bean must be annotated with @Component and use JavaBean-based property binding.

You can also avoid the problem by annotating the constructor with @Autowired to ensure that JavaBean-based binding is still used:

For most users, this updated logic will allow for simpler @ConfigurationProperties classes. If, however, you have a @ConfigurationProperties and you want to inject beans into the constructor rather than binding it, you’ll now need to add an @Autowired annotation.

Comment From: sergmain

Thanks for additional info