It seems ConditionalOnProperty
only works for properties within the classpath like application.properties
in the resources folder. I need a property that an end-user can turn on and off via an external property. An example is extremely simple:
Configuration class reads the external properties. Sys.out
to show it's reading the file properly.
@Configuration
@EnableAutoConfiguration
@PropertySource("file:/Users/end.user/MyApp/config/MyApp.properties")
public class PropertyConfigurer {
@Value("${featureOne}")
private String featureOne;
@PostConstruct
public void init() {
System.out.println("FeatureOne : " + featureOne);
}
}
Feature class, this component class will be put in the application context to be able to be used if the property is enabled via ConditionalOnProperty
, otherwise the component is never instantiated.
@Component
@ConditionalOnProperty(name="featureOne", havingValue = "true")
public class FeatureOne {
@PostConstruct
public void init() {
System.out.println("Feature initialized");
}
}
As you can imagine I am never seeing "Feature initialized" due to the "featureOne" property not being available to the spring context until after this class has been constructed. If there was some way to force the properties from @PropertySource
to be available to the spring context upon class instantiation. Or any other way? I also tried @DependsOn
the PropertyConfigurer
from FeatureOne
but that interestingly didn't work either.
It seems ConditionalOnProperty only works for properties within the classpath like application.properties in the resources folder.
Not exactly. It also works with external files, provided that they are specified as program arguments during running with spring.config.location
option.
--spring.config.location=file:/Users/end.user/MyApp/config/MyApp.properties
The problem is @PropertySource
is being read by org.springframework.context.annotation.ConfigurationClassParser::processPropertySource
method. And @ConditionalOnProperty
is being validated at org.springframework.boot.autoconfigure.condition.OnPropertyCondition::getMatchOutcome
method.
If you were to put a debug at these two places, you will find that getMatchOutcome is executed first and then processPropertySource. And hence your condition doesn't work with @PropertySource
.
But if you were to run your application as java -jar abc.jar --spring.config.location=file:/Users/end.user/MyApp/config/MyApp.properties
, then these properties are added to context.environment and hence @ConditionalOnProperty
works.
If there was some way to force the properties from @PropertySource to be available to the spring context upon class instantiation
I am not sure if there is any way to do this. But given your requirement (I need a property that an end-user can turn on and off via an external property), using spring.config.location
would be a prudent choice.