PropertySourcesPlaceholderConfigurer with highest priority - spring-boot

in my Spring Boot project I have the default application.properties in resources directory, I also configured Spring to load a properties file from file system (in working directory), called config.properties. some properties are redefined in the config.properties file, I want them have higher priority and overwrite properties defined in application.properties.
here is the PropertySourcesPlaceholderConfigurer bean :
#Configuration
public class Config {
#Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
PropertySourcesPlaceholderConfigurer properties =
new PropertySourcesPlaceholderConfigurer();
properties.setLocation(new FileSystemResource("config.properties"));
properties.setIgnoreResourceNotFound(false);
properties.setOrder(Ordered.HIGHEST_PRECEDENCE);
return properties;
}
}
but it does not work. the values in application.properties are applied, not config.properties. I tried to change setOrder(Ordered.HIGHEST_PRECEDENCE); to setOrder(Ordered.LOWEST_PRECEDENCE); nothing happened.

You can try call the method PropertySourcesPlaceholderConfigurer.setLocalOverride(boolean localOverride)
properties.setLocalOverride(true)
See for details: https://docs.spring.io/spring-framework/docs/4.1.6.RELEASE_to_4.2.0.RC1/Spring%20Framework%204.1.6.RELEASE/org/springframework/core/io/support/PropertiesLoaderSupport.html#setLocalOverride-boolean-

Related

Spring configuration from yaml - combining #ConfigurationEnabled loading for parametrized file name

I'm having a problem probabably quite unique. I have two applications in the same project, using two different spring configuration files.
When I run them I manually load the context
context = new ClassPathXmlApplicationContext("hal.context.xml");
context.registerShutdownHook();
and I specify the required spring context file in each of them.
The problems comes from the configuration, because I have two configuration files stored in yaml files.
My best solution would be to use the Spring Boot facility to load the configuration (they have the same structure) in a POJO using
#org.springframework.context.annotation.Configuration("configuration")
#ConfigurationProperties
#EnableConfigurationProperties
and
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("filename"));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
return propertySourcesPlaceholderConfigurer;
}
I cannot find a way to load the configuration in a parametrised way... Is there any option combining this and perhaps
<bean id="yamlProperties" class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean">
<property name="resources" value="classpath:hal.config.yml"/>
</bean>
but instead of using as property placeholder <context:property-placeholder properties-ref="yamlProperties"/> to find a way to automatically generate the POJO with the configuration.
Thank you in advance
Luca
You could separate the configuration values by using two different prefixes (one for each config file):
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setPlaceholderPrefix("${app1:");
propertySourcesPlaceholderConfigurer.setPlaceholderSuffix("}");
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("app1_config_filename"));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
return propertySourcesPlaceholderConfigurer;
}
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setPlaceholderPrefix("${app2:");
propertySourcesPlaceholderConfigurer.setPlaceholderSuffix("}");
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("app2_config_filename"));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
return propertySourcesPlaceholderConfigurer;
}
Then when injecting configuration values into your beans you can do:
#Value("{$app1:myVal}")
String myVal;
and
#Value("{$app2:myVal}")
String myVal;
Into beans from app1 and app2
Hope this helps

Setting class level annotation values from application.yml

I was trying to externalise my configuration of a class level annotation using allication.yaml. But the spring is not loading it right. Any idea how to do this ?
Here is my Service classI am trying to set
#Service
#DefaultProperties(threadPoolProperties = {
#HystrixProperty(name = "coreSize", value =
"${cyclone.hystrix.lease.thread.coreSize}") })
public class LeaseService {
}
And application.yml
cyclone:
hystrix:
lease:
thread:
coreSize: 10
Getting an error --
java.lang.IllegalArgumentException: bad property value. property name 'coreSize'. Expected int value, actual = ${cyclone.hystrix.lease.thread.coreSize}
I can load the same property using #Value("${cyclone.hystrix.lease.thread.coreSize}"). But not working on the above mentioned case.
Any help on how to properly configure this ?
In order to make spring evaluate placeholders you need to register a PropertySourcesPlaceholderConfigurer bean using a static #Bean method when using #Configuration classes as follows:
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
According to the JavaDoc:
Specialization of PlaceholderConfigurerSupport that resolves ${...} placeholders within bean definition property values and #Value annotations against the current Spring Environment and its set of PropertySources.

about spring boot Profile can not work

when I use command
mvn spring-boot:run -Dspring.profiles.active=web
my project is running,but #Profile("web") bean code not used,that only use
properties which the bean write by
#Profile("default")
how can I change for it,and the properties change to web profile?
#Profile("default")
#Bean
static public PropertySourcesPlaceholderConfigurer defaultPropertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer p = new PropertySourcesPlaceholderConfigurer();
Resource[] resourceLocations = new Resource[] { new ClassPathResource("job.core.properties") };
p.setLocations(resourceLocations);
return p;
}
#Profile("web")
#Bean
static public PropertySourcesPlaceholderConfigurer prodWebPropertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer p = new PropertySourcesPlaceholderConfigurer();
Resource[] resourceLocations = new Resource[] {new ClassPathResource("job.core.ris.properties") };
p.setLocations(resourceLocations);
return p;
}
job.core.ris.properties
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://192.168.0.68:3306/job_ris?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8
db.user=root
db.password=
job.core.properties
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://192.168.0.68:3306/dev?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8
when I use action then,show this
Work with the framework not against/around it. Spring Boot has build in support to load profile specific application.properties files.
Instead of trying to shoehorn multiple PropertyPlaceholderConfigurer into a Spring Boot application. Create an application.properties and application-web.properties containing your properties.
application.properties
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://192.168.0.68:3306/dev?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8
application-web.properties
db.jdbcUrl=jdbc:mysql://192.168.0.68:3306/job_ris?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8
db.user=root
db.password=
(notice the missing db.driverClass you only need to include the different properties).
Next remove your custom #Bean annotated methods and let Spring Boot do the heavy lifting.
Pro Tip: Judging from the names of the properties you also have a custom #Bean for your DataSource. Instead of using custom names you probably want to use the spring.datasource.* properties and let Spring Boot create/manage your datasource.

Spring #Value assigning null to variable. #PropertySource

I am trying to use the #Value annotation on a variable to assign a value, but the value getting assigned is null. What am I doing wrong? I am using the java spring configuration using #Configuration. I am also using #PropertySource to point to a properties file.
#Configuration
#PropertySource("classpath:application.properties")
public class SpringConfiguration {
#Value("${app_prop_1}") Integer aValue;
#Bean
public Integer getInteger() {
return new Integer(aValue); // throws NullPointerException
}
}
The application.properties files is in the maven resources folder of project. It has following content:
app_prop_1=2000
When you add #Value annotation, there is a need to add
//To resolve ${} in #Value
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
This will resolve the ${} expression.
Source

#Value is not injected

I'm trying to inject value from properties file into a spring configuration class as follows:
#Configuration
#EnableWebMvc
public class ImagesContext {
#Autowired
#Value("${some.property.com}")
private String property;
#Bean
public MyClass getMyClass() {
return new MyClass(property);
}
}
But the property is not injected correctly. Instead, when I debug, I see that the property string contains ${some.property.com} and not the string value itself.
The #Value annotation is processed by AutowiredAnnotationBeanPostProcessor which is typically registered if you have a <component-scan> or <annotation-config> configuration in XML (or directly with a bean definition). You need to add either of those, probably <annotation-config>
Add the following bean declaration in your Config class if not done already
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
In order for #Value annotations to work PropertySourcesPlaceholderConfigurer should be registered. It is done automatically when using <context:property-placeholder> in XML, but should be registered as a static #Bean when using #Configuration.

Resources