java - How to build custom PropertySource for binding to @ConfigurationProperties -


we're creating new propertysource uses database it's repository. idea can update property values @ runtime.

at same time, we'd use @configurationproperties can include validation use application-{profile} naming conventions.

however, appears values of @configurationproperties loaded "applicationconfig: [path/to/config]" propertysource's. example, following test:

private final string overriden_value = "overriden value";  @before public void before() {      logger.debug("property sources are: ");      for(iterator<?> = env.getpropertysources().iterator(); it.hasnext(); ) {         propertysource<?> propertysource = (propertysource<?>) it.next();         logger.debug(propertysource.getname());     }      environmenttestutils.addenvironment("integrationtest", env, "some.prefix.overridable-property=" + overriden_value);  }  @test public void testoverridingdefaultproperties() {      logger.debug("mutablepropertysources value: {}", env.getproperty("some.prefix.overridable-property"));     logger.debug("@configurationproperties value: {}", testproperties.getoverridableproperty());      assert.assertequals(overriden_value, testproperties.getoverridableproperty());  } 

produces output:

property sources are:      systemproperties     systemenvironment     random     integrationtest     applicationconfig: [classpath:/path/to/my/application.yml]  mutablepropertysources value: overriden value @configurationproperties value: default value 

for more context, asked question on spring boot's github here.

thanks spring boot folks. pointed me spring cloud context

http://projects.spring.io/spring-cloud/spring-cloud.html#customizing-bootstrap-property-sources

looks trick.

update:

since had additional database-backed propertysource written needed refresh @configurationproperties @ runtime. @ same time didn't want refresh @configurationproperties. accomplish refresh did following:

  1. created annotation called @reloadableproperties
  2. created following utility bean utilizes spring boot's configurationpropertiesbindingpostprocessor
 /**  *   * helper bean reload {@code @configurationproperties}  * if {@code @configurationproperties} bean annotated   * {@code @reloadableproperties}.  *   * @author jonathan martin  * @since 2.0.0  *   * @see reloadableproperties  * @see configurationpropertiesbindingpostprocessor  *  */ public class configurationpropertiesreloader {      private final applicationcontext context;      private final configurationpropertiesbindingpostprocessor processor;      @autowired     public configurationpropertiesreloader(applicationcontext context,  configurationpropertiesbindingpostprocessor processor) {         this.context = context;         this.processor = processor;     }      /**      * reload {@code @configurationproperties}      * annotated {@code @reloadableproperties}.      */     public void reload() {         map beans = context.getbeanswithannotation(reloadableproperties.class);         (map.entry entry : beans.entryset()) {              string beanname = entry.getkey();             object bean = entry.getvalue();              configurationproperties annotation = annotationutils.findannotation(bean.getclass(), configurationproperties.class);              // reload bean if it's @configurationproperties             // can't check instance of configurationpropertiesholder              // because uses package scope.             if (annotation != null) {                 processor.postprocessbeforeinitialization(bean, beanname);             }          }     }  }  

now if inject utility bean test , invoke reload, test passes.


Comments