Injecting property files overriding the one defined in the application - java

I need some help on injecting property value to a bean which is defined outside the web application.
The web application has a property file under src/main/resource.The spring application context xml has the property place holder defined as
<context:property-placeholder
location="classpath:test.properties,file:/etc/test1.properties"
ignore-resource-not-found="true"
/>
where test1.properties is another file which resides outside the application.The bean is injected with the property which is defined in the application (test.properties) ,but I want to inject the property that is defined in test1.properties (ideally the idea is to override the property values from application and read the one defined outside the application).
Thanks.

Hi use like below in applicationContext.xml
<util:properties id="property" location="classpath:test.properties"/>
In Java,
#Autowired
protected Properties property;

I guess this is what you are looking for
<context:property-placeholder location="file:c:/kp/sec.properties" order="1" ignore-resource-not-found="true" ignore-unresolvable="true" />
<context:property-placeholder location="classpath:kp-props.properties" order="2" />
If the file sec.properties exists take the value from sec.properties, if file or properties does not exist take the property from kp-props.properties file from resources directory(if the property is not found in either of place application will fail)
And say you have property my.prop and you can inject the property as follows.
#Component
public class KPProps {
#Value("${my.prop}")
private int props;
public void print(){
System.out.println(props);
}
}

Related

What is the Best way to get the values from the Properties File in Spring?

I have used the following ways to get the values from the properties. But I would like to know which one of these is the best to use to follow the coding standard? Also, are there any other ways that we can get the values from the properties file in Spring?
PropertySourcesPlaceholderConfigurer
getEnvironment() from the Spring's Application Context
Spring EL #Value
Along with the other configuration classes (ApplicationConfiguration etc.) I create a class with the annotation #Service and here I have the following fields to access the properties in my file:
#Service
public class Properties (){
#Value("${com.something.user.property}")
private String property;
public String getProperty (){ return this.property; }
}
Then I can autowire the class and get the properties from my properties file
The answer is,
it depends.
If the properties are configuration values,
then configure a propertyConfigurer
(below is an example for a Spring xml configuration file).
<bean id="propertyConfigurer"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:configuration.properties</value>
<value>classpath:configuration.overrides.properties</value>
</list>
</property>
</bean>
When configured this way,
the properties from the last file found override those found earler
(in the locations list).
This allows you to ship the standard configuration.properties file bundled in the war file and store a configuration.overrides.properties at each installation location to account for installation system differences.
Once you have a propertyConfigurer,
annotate your classes using the #Value annotation.
Here is an example:
#Value("${some.configuration.value}")
private String someConfigurationValue;
It is not required to cluster the configuration values into one class,
but doing so makes it easier to find where the values are used.
#Value will be the simple and easy way to use, as it will inject value from property file to your field.
Both the older PropertyPlaceholderConfigurer and the new PropertySourcesPlaceholderConfigurer added in Spring 3.1 resolve ${…} placeholders within bean definition property values and #Value annotations.
unlike getEnvironment
using property-placeholder will not expose the properties to the
Spring Environment – this means that retrieving the value like this
will not work – it will return null
when you are using <context:property-placeholder location="classpath:foo.properties" /> and you use env.getProperty(key); it will always return null.
see this post for the problem using getEnvironment : Expose <property-placeholder> properties to the Spring Environment
Moreover, in Spring Boot you can use #ConfigurationProperties to define your own properties with hierarchical and type-safe in application.properties. and you don't need to put #Value for every field.
#ConfigurationProperties(prefix = "database")
public class Database {
String url;
String username;
String password;
// standard getters and setters
}
in application.properties:
database.url=jdbc:postgresql:/localhost:5432/instance
database.username=foo
database.password=bar
Quote from : properties with spring

Spring - #Value returns null

I have a properties file under /src/main/resources/ and I want to load data from it using Spring.
In my Spring-context.xml I have this :
<context:property-placeholder location="classpath:UserUtil.properties" />
and also have <context:component-scan base-package="com.myApp" />
and in my class I load it like :
#Value("${injectMeThis}")
private String injectMeThis;
but the value is always null
EDIT:
to check if the value, I use this :
System.out.println(new myClass().getInjectMeThis());
System.out.println(new myClass().getInjectMeThis());
Spring will only parse #Value annotations on beans it knows. The code you use creates an instance of the class outside the scope of Spring and as such Spring will do nothing with it.
Assuming you have setup your application context correctly a #Value cannot be null as that will stop the correct startup of your application.
Your XML file contains a <context:component-scan /> assuming myClass is part of that package the easiest solution is to add #Component to myClass and then retrieve the instance from the context instead of creating a new instance.
In your class, add class level annotation #PropertySource("UserUtil.properties"). This should solve the problem.

Spring property initialization

I have an xml configurable Spring context with the following property placeholders:
<context:property-placeholder
properties-ref="dbProperties" location="classpath:logmessages.properties" order="2"/>
<context:property-placeholder location="classpath:application.properties" order="1"/>
DB properties configuration bean is as follows:
<bean id="dbProperties"
class="com.example.DatabasePropertiesLoader">
<property name="path" value="${db.path}"/>
</bean>
As it comes from the name, this bean loads some properties from the database, for example endpoints and credentials to other services. However, to access the database that keeps this properties it also needs credentials, which are kept in application.properties:
public class DatabasePropertiesLoader extends AbstractFactoryBean<Properties> {
private String path;
#Override
protected Properties createInstance() throws Exception {
// logic loading properties
}
#Override
public Class<Properties> getObjectType() {
return Properties.class;
}
}
Path property kept in application.properties file:
db.path=localhost:7777
As you see, this bean requires "path" property to be injected to be created.
However, it can't be done, because injected value is null. I guess that Spring only knows about application.properties file, not about its contents. Is there any way to solve this?
You need to tell spring to use the properties as below.
#Value("${db.path}")
private String path;

Spring 3.2 properties issue with #Value

I've searched stackoverflow, read docs and can not seem to get my #Value("${myproperty.value}") to give me anything other than null.
I have some beans that I have defined in my spring-servlet.xml as well the properties file.
<!-- Load properties files -->
<context:property-placeholder location="classpath:MyProperties.properties" ignore-unresolvable="true" />
The properties file gets loaded without errors. In the same xml I have defined a bean.
<bean id="pushNotification" class="com.mydomian.actions.MyClass"/>
In the bean I have properties that use the #Value.
private #Value("${some.property}") String propertyValue;
My properties are always null.
You need to declare
<context:annotation-config />
to enable annotation processing.

Loading a Map in field of Class Object, before the Class instance is returned by getBean method of Spring?

I have a .properties file having 10 key-values pairs say age =10, name=Jon etc. I have configured a bean in spring which has a map as a member variable.
When the bean is loaded by Spring once I call the getBean method, before that the Map should be loaded with the properties from files. How to do that ?
I know this should be done in one of the lifecycle methods like afterPropertiesSet using InitializingBean or init-method configuration. Is there any other better way to do this ?
You can enable annotations in your beans:
<context:annotation-config />
Then you can define method with #PostConstruct annotation. Spring will execute it during bean initialization process:
class MyBean {
private Map<String, String> properties;
#PostConstruct
public void initialize() {
// read properties and initialize map
}
}
Another option is to inject Properties directly into your bean and provide map-like API to access them:
<util:properties id="myProperties" location="classpath:my-props.properties">
<bean id="myBean" class="com.example.MyBean">
<property name="properties" ref="myProperties" />
</bean>
you can use context property-placeholder within XML spring configuration file using ${...} or from java class configuration file using #value.

Categories