1

I have a @ConfigurationProperties class that is no longer binding to a YML property source that gets resolved via Spring Cloud Config after upgrading to Hoxton.SR7. This code works fine using Hoxton.SR4 with the latest Spring Boot 2.2.9.RELEASE. Now, my properties are not bound and I'm receiving NPEs when I try to reference them. Following is a snapshot of my code:

@Configuration
public class MyConfiguration {

  @Bean
  public MyPropertiesBean myPropertiesBean() {
    return new MyPropertiesBean(); 
  }

}
@ConfigurationProperties(prefix = "com.acme.properties")
@Validated
public class MyPropertiesBean {
  ...
}

In src/main/resources/META-INF/spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.acme.MyConfiguration

Any ideas why my @ConfigurationProperties class doesn't bind after upgrading Spring Cloud to Hoxton.SR7?

Keith Bennett
  • 733
  • 11
  • 25
  • Anything in the logs trying to reach config server? There should be – spencergibb Aug 05 '20 at 15:26
  • Very interesting. I see ```2020-08-05 | 15:42:16.885 | main | INFO | c.c.c.ConfigServicePropertySourceLocator | Connect Timeout Exception on Url - http://configuration-service:8081. Will be trying the next url if available``` in the logs. What's strange to me is simply by changing Hoxton.SR7 back to Hoxton.SR4, I don't receive this error. – Keith Bennett Aug 05 '20 at 16:11
  • @spencergibb I apologize. That log message was due to the fact that the Spring Cloud Config service was still starting. I eventually see the properties display in the logs, so it looks like Spring Cloud Config can find and load the properties. However, I am seeing the following in the logs right before I see the NPE: ```2020-08-05 | 15:42:38.008 | main | WARN | i.InstanceMetadataServiceResourceFetcher | Fail to retrieve token```. – Keith Bennett Aug 05 '20 at 16:37
  • I don't know what `InstanceMetadataServiceResourceFetcher` is. – spencergibb Aug 05 '20 at 16:48
  • @spencergibb After doing more debugging, I think the NPE is a symptom of the problem I describe in this post: https://stackoverflow.com/questions/63271529/error-encountered-after-upgrading-to-spring-cloud-hoxton-sr7-from-hoxton-sr4. – Keith Bennett Aug 05 '20 at 18:56
  • @spencergibb It ends up that according to https://github.com/spring-cloud/spring-cloud-aws/issues/556, the stack trace related to ```InstanceMetadataServiceResourceFetcher``` is just a warning and totally unrelated to the original problem I had, which is that my ```@ConfigurationProperties``` object doesn't bind to the YML property source. Is there anything that has changed in recent releases that would cause my code to no longer work? Like I said in my original post, the code snippet I posted works just fine with ```Hoxton.SR4```. – Keith Bennett Aug 05 '20 at 22:35
  • @spencergibb I've identified the problem. My microservice starts fine all the way through Spring Cloud Hoxton.SR6/Spring Boot 2.2.9.RELEASE. Once I upgrade to Hoxton SR7, ConfigurationProperties do not bind. The problem appears to be the latest Spring Cloud Aws release (2.2.3.RELEASE) as documented at https://spring.io/blog/2020/08/04/spring-cloud-hoxton-sr7-has-been-released. To prove this, with Hoxton SR6, I upgraded the SC AWS libraries to the 2.2.3.RELEASE versions and got the same errors. With Hoxton.SR7, I downgraded the SC AWS libraries to the 2.2.2.RELEASE and my service starts fine. – Keith Bennett Aug 06 '20 at 14:34
  • @spencergibb I've opened a GitHub issue for this: https://github.com/spring-cloud/spring-cloud-aws/issues/641. It looks like others are running into the exact same problem (see https://github.com/spring-cloud/spring-cloud-aws/issues/640, for example). – Keith Bennett Aug 06 '20 at 16:57

1 Answers1

0

You're mixing two ways of binding properties: class and method.

Using a method and @Bean annotation:

@Configuration
public class MyConfiguration {

  @Bean
  @ConfigurationProperties(prefix = "com.acme.properties")
  @Validated
  public MyPropertiesBean myPropertiesBean() {
    return new MyPropertiesBean(); 
  }

}

This will create MyPropertiesBean and store it inside the application context for you to inject.

Class level bean declaration also creates a bean for you:

@Configuration
@ConfigurationProperties(prefix = "com.acme.properties")
@Validated
public class MyPropertiesBean {
  ...
}

This will also store a bean.

Although, you should be getting a runtime error when you try to inject MyPropertiesBean as now in your case there's two beans of the same type and Spring cannot resolve with only the type.

George
  • 2,820
  • 4
  • 29
  • 56