Setup
- Spring Boot 2.6.0
- Spring Cloud Config 3.1 RC1
- Apache Maven 3.8.x
- OpenJDK 11
Overview
I have a multi-module Apache Maven project that is set up with the following modules:
- bootstrap: contains a
PropertySourceLocator
forBootstrapConfiguration
, defined inspring.factories
file. - starter: depends on bootstrap, and it's a (servlet-based) web application
- reference: deploys the starter application using the Maven Cargo plugin, deploying into an Apache Tomcat 9.0.55
Runtime
- The starter module declares a configuration class, annotated with
@PropertySource("wa.properties")
. Thiswa.properties
on the classpath of the starter module has a setting:cas.authn.syncope.name=Starter
- The starter module has a
ServletInitializer
that sets thespring.config.name
property to "wa" when building the spring application. - The reference module only has a
wa-embedded.properties
file on the classpath with a setting:cas.authn.syncope.name=Embedded
- The reference module starts with the spring activated profiles:
embedded,all
Note: the cas.authn.syncope.name
is bound to a Java POJO, CasConfigurationProperties
, that is annotated with @ConfigurationProperties("cas")
.
Observation
The following bean in the application exists, simplified for this post:
@Bean
@ConditionalOnMissingBean(name = "something")
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public Something something(ApplicationContext ctx, CasConfigurationProperties cas) {
...
}
- If I look at the contents of
cas.getAuthn().getSyncope().getName())
, it shows: "Starter" - If I look at
ctx.getEnvironment().getProperty("cas.authn.syncope.name")
, it shows "Embedded".
In other words, property binding used during the bootstrapping process does not match the actual environment for the application's context.
Analysis
It appears that when the bootstrap application context is created,
wa-embedded.properties
, a profile-specific property is not read. In fact, the only property source that is used for binding iswa.properties
as part of "localProperties", which I believe comes from@PropertySource("wa.properties")
. Nothing else is read or found.Then, property binding takes place binding
CasConfigurationProperties
andcas.authn.syncope.name
initialized from@PropertySource("wa.properties")
. The value of this property is set toStarter
.Then, the application servlet context is initialized and its environment is post-processed with profiles and the appropriate listener and Spring beans are created. In particular, this bean:
@Bean
@ConditionalOnMissingBean(name = "something")
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public Something something(ApplicationContext ctx, CasConfigurationProperties cas) {
...
}
...shows that ctx
is the actual application context with an environment that is post-processed via all profiles and shows ctx.getEnvironment().getProperty("cas.authn.syncope.name")
as "Embedded".
However, CasConfigurationProperties
was processed using the Bootstrap context only, and its equivalent property shows "Starter".
...which means the bean would be created using the wrong values in CasConfigurationProperties
.
Research
This setup works OK using Spring Boot 2.5.6 and Spring Cloud 3.0.5. I don't think anything in Spring Boot has changed that would affect this, but I do see a number of differences in Cloud between 3.0 and 3.1.
I am not sure I can create a reproducer to adequately showcase this. I'll try. In the meantime, could you evaluate this and see if this might be seen as a bug, or misconfiguration of some kind?