Wednesday, January 16, 2019

How to Read Properties File in Spring Framework

This post shows how to read properties file in Spring framework using XML configuration or by using @PropertySource Annotation.

There are scenarios when you have to provide few configuration properties in order to configure the resource like in case of Database you need to provide driver class, DB location, user name and password or in case of sending mail through your application you need to provide properties like SMTP host, user name, password.

Many a times developers put all these details in the Spring XML configuration file itself which is not a good practice. It’s better to put them in a properties file that way you can have specific properties files like db.properties, mail.properties, app.properties etc. and read the property value from that properties file rather than hard coding them. Another advantage is that any change in any setting will require you to change the specific properties file only.

In Spring reading properties file and setting property values can be done using-

  • XML configuration
  • Using @PropertySource Annotation

Reading properties file in Spring using XML configuration

Suppose you have your Database properties in a properties file called db.properties residing under config folder under resources folder.

db.properties (for connecting to MYSQL DB)

db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/netjs
db.username=root
db.password=password
pool.initialSize=5

Then you can use ${property key} placeholders in <bean> definitions. In order to resolve these placeholders you must register a PropertySourcesPlaceholderConfigurer. This happens automatically when using <context:property-placeholder> in XML.

Full XML configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!--  For reading properties files --> 
    <context:property-placeholder location="classpath:config/db.properties" />
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
        <property name="dataSource" ref="dataSource"></property>  
    </bean>  
    <bean id="employeeDAO" class="org.netjs.daoimpl.EmployeeDAOImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>  
    </bean>
    
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <property name="driverClassName" value = "${db.driverClassName}" />
        <property name="url" value = "${db.url}" />
        <property name="username" value = "${db.username}" />
        <property name="password" value = "${db.password}" />
        <property name="initialSize" value = "${pool.initialSize}" />
    </bean>

</beans>

Reading properties file in Spring using @PropertySource Annotation

Spring also has @PropertySource annotation (added in Spring 3.1) for reading properties file. It can be used with @Value annotation to read the value of the given property.

Example Program

Given a file db.properties (as used above) containing the key/value pair, the following @Configuration class uses @PropertySource along with @Value annotation to read properties.

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@Configuration
@PropertySource("classpath:config/db.properties")
public class DBConfig {
    @Value("${db.driverClassName}")
    private String dbDriverClass;
    @Value("${db.url}")
    private String dbUrl;
    @Value("${db.username}")
    private String dbUser;
    @Value("${db.password}")
    private String dbPwd;
    
    @Bean
    public BasicDataSource dataSource() {
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName(dbDriverClass);
        ds.setUrl(dbUrl);
        ds.setUsername(dbUser);
        ds.setPassword(dbPwd);
        return ds;
    }
    
    //register PropertySourcesPlaceholderConfigurer
    //in order to resolve ${...} placeholders
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
        return new PropertySourcesPlaceholderConfigurer();
    }
} 

Here you can see how fields are annotated with @Value(property key name) annotation in order to map them with the specific property in the .properties file.

In order to resolve ${...} placeholders in <bean> definitions or @Value annotations using properties from a PropertySource, one must register a PropertySourcesPlaceholderConfigurer. This happens automatically when using <context:property-placeholder> in XML (in above example), but must be explicitly registered using a static @Bean method when using @Configuration classes. That’s what is done in DBConfig class.

If you want to run this you can use the following class -

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class App {

 public static void main(String[] args) {
  AbstractApplicationContext context = new AnnotationConfigApplicationContext
   (DBConfig.class);
  BasicDataSource ds = (BasicDataSource)context.getBean("dataSource");
  System.out.println("URL - " + ds.getUrl());
 }

}

Using @PropertySource Annotation with Spring’s Environment

Rather than using @Value annotation, Environment should be used to read properties file in Spring. Actually @PropertySource annotation adds a PropertySource to Spring's Environment so that can be used to make your code simpler.

Reading properties file example with Environment

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;

@Configuration
@PropertySource("classpath:config/db.properties")
public class DBConfig {
 @Autowired
 private Environment env;
 
 @Bean
 public BasicDataSource dataSource() {
  BasicDataSource ds = new BasicDataSource();
  System.out.println("User " + env.getProperty("db.username"));
  ds.setDriverClassName(env.getProperty("db.driverClassName"));
  ds.setUrl(env.getProperty("db.url"));
  ds.setUsername(env.getProperty("db.username"));
  ds.setPassword(env.getProperty("db.password"));
  return ds;
 }
}

In that case you just need to Autowire (or Inject) Environment into your Config class and use Environment object to get property value.

Property overriding with @PropertySource

In cases where a given property key exists in more than one .properties file, the last @PropertySource annotation processed will 'win' and override. For example, given two properties files a.properties and b.properties, consider the following two configuration classes that reference them with @PropertySource annotations:

 @Configuration
 @PropertySource("classpath:/com/myco/a.properties")
 public class ConfigA { }

 @Configuration
 @PropertySource("classpath:/com/myco/b.properties")
 public class ConfigB { }

The override ordering depends on the order these classes are registered with the application context.

Using ignoreResourceNotFound attribute with @PropertySource

In case your properties file is optional and you don't want exception to be thrown if it doesn't exist you can use ignoreResourceNotFound attribute and set it as true. Default is false.

As example

If you want to load test.properties file and want to ignore the resource if not found then you can do it as -

@Configuration
@PropertySource(value="classpath:config/test.properties", ignoreResourceNotFound=true)
public class DBConfig {
 @Autowired
 private Environment env;
 ..........
 ..........

That's all for this topic How to Read Properties File in Spring Framework. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Data access in Spring framework
  2. Select query using JDBCTemplate in Spring framework
  3. How to inject prototype scoped bean in singleton bean
  4. @Resource annotation in Spring autowiring
  5. Using Spring Profiles to Switch Environment

You may also like-

  1. What is Dependency Injection in Spring
  2. Spring example program using automatic configuration
  3. Difference between Array and ArrayList in Java
  4. fail-fast Vs fail-safe iterator in Java
  5. Executor and ExecutorService in Java concurrency
  6. Difference between CountDownLatch and CyclicBarrier
  7. Java Multi-threading interview questions
  8. Unzipping files in Java