147

I am using spring. I need to read values from properties file. This is internal properties file not the external properties file. Properties file can be as below.

some.properties ---file name. values are below.

abc = abc
def = dsd
ghi = weds
jil = sdd

I need to read those values from the properties file not in traditional way. How to achieve it? Is there any latest approach with spring 3.0?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
user1016403
  • 12,151
  • 35
  • 108
  • 137

11 Answers11

209

Configure PropertyPlaceholder in your context:

<context:property-placeholder location="classpath*:my.properties"/>

Then you refer to the properties in your beans:

@Component
class MyClass {
  @Value("${my.property.name}")
  private String[] myValues;
}

To parse property with multiple comma-separated values:

my.property.name=aaa,bbb,ccc

If that doesn't work, you can define a bean with properties, inject and process it manually:

<bean id="myProperties"
      class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="locations">
    <list>
      <value>classpath*:my.properties</value>
    </list>
  </property>
</bean>

and the bean:

@Component
class MyClass {
  @Resource(name="myProperties")
  private Properties myProperties;

  @PostConstruct
  public void init() {
    // do whatever you need with properties
  }
}
Null
  • 1,950
  • 9
  • 30
  • 33
mrembisz
  • 12,722
  • 7
  • 36
  • 32
  • Hi mrembisz, Thanks for your reply. i already configured propert-placeholder to read values from external properties file. but i have one properties file inside resources folder. i need to read and inject. i need to inject all the values into list. Thanks! – user1016403 Feb 13 '12 at 12:40
  • Edited as suggested by @Ethan. Thanks for update, could not accept original edit, it was too late already. – mrembisz Mar 26 '13 at 16:15
  • 2
    For the case where you are dealing with comma separated values perhaps consider what is being proposed here by using EL: http://stackoverflow.com/questions/12576156/reading-a-list-from-properties-file-and-load-with-spring-annotation-value – arcseldon Aug 20 '13 at 03:01
  • @user36123 Yea, that should work too but I think it's more readable to have an array and avoid calcuations in EL. – mrembisz Aug 20 '13 at 07:00
  • 2
    How do we use `aaa`? Is it `@Value(${aaa}) private String aaa;` then we can `System.out.println(aaa)`??????? –  Feb 13 '14 at 05:19
  • 2
    @user75782131 More precisely `@Value("${aaa}")`, mind the quotes. And yes, you can print it except not in the constructor because constructor is executed before values are injected. – mrembisz Feb 13 '14 at 10:22
  • You can avoid ```@PostConstruct``` with implementing ```org.springframework.beans.factory.InitializingBean``` and overriding ```public void afterPropertiesSet()``` method. – franta kocourek Feb 26 '16 at 06:46
  • do i have to do it like this? is there a way like `int prop = Environment.getProperty("prop.defined.in.the.file");` – yılmaz Dec 10 '21 at 21:19
57

There are various ways to achieve the same. Below are some commonly used ways in spring-

  1. Using PropertyPlaceholderConfigurer

  2. Using PropertySource

  3. Using ResourceBundleMessageSource

  4. Using PropertiesFactoryBean

    and many more........................

Assuming ds.type is key in your property file.


Using PropertyPlaceholderConfigurer

Register PropertyPlaceholderConfigurer bean-

<context:property-placeholder location="classpath:path/filename.properties"/>

or

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations" value="classpath:path/filename.properties" ></property>
</bean>

or

@Configuration
public class SampleConfig {
 @Bean
 public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
  return new PropertySourcesPlaceholderConfigurer();
  //set locations as well.
 }
}

After registering PropertySourcesPlaceholderConfigurer, you can access the value-

@Value("${ds.type}")private String attr; 

Using PropertySource

In the latest spring version you don't need to register PropertyPlaceHolderConfigurer with @PropertySource, I found a good link to understand version compatibility-

@PropertySource("classpath:path/filename.properties")
@Component
public class BeanTester {
    @Autowired Environment environment; 
    public void execute() {
        String attr = this.environment.getProperty("ds.type");
    }
}

Using ResourceBundleMessageSource

Register Bean-

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
  <property name="basenames">
    <list>
      <value>classpath:path/filename.properties</value>
    </list>
  </property>
</bean>

Access Value-

((ApplicationContext)context).getMessage("ds.type", null, null);

or

@Component
public class BeanTester {
    @Autowired MessageSource messageSource; 
    public void execute() {
        String attr = this.messageSource.getMessage("ds.type", null, null);
    }
}

Using PropertiesFactoryBean

Register Bean-

<bean id="properties"
      class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="locations">
    <list>
      <value>classpath:path/filename.properties</value>
    </list>
  </property>
</bean>

Wire Properties instance into your class-

@Component
public class BeanTester {
    @Autowired Properties properties; 
    public void execute() {
        String attr = properties.getProperty("ds.type");
    }
}
Community
  • 1
  • 1
  • To use a PropertySourcesPlaceholderConfigurer you must normally set a location or resource otherwise you couldn't access a properties file. You can use e.g. ClassPathResource generalProperties = new ClassPathResource("general.properties"); – M46 Jun 16 '20 at 15:46
49

In configuration class

@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {
   @Autowired
   Environment env;

   @Bean
   public TestBean testBean() {
       TestBean testBean = new TestBean();
       testBean.setName(env.getProperty("testbean.name"));
       return testBean;
   }
}
mokshino
  • 1,435
  • 16
  • 11
  • In this example, would you simply use a different `app.properties` in production v. testing? In other words, would part of your deployment process be to replace `app.properties` with production values? – Kevin Meredith Jul 15 '15 at 16:54
  • 1
    @KevinMeredith yes, you can, just split your spring configuration by Profile annotation http://stackoverflow.com/questions/12691812/can-propertysources-be-chosen-by-spring-profile#answer-14167357 – mokshino Jul 27 '15 at 13:56
  • @KevinMeredith we use a folder outside deploy war: like c:\apps\sys_name\conf\app.properties . Deployment process gets simplified and less error-prone. – jpfreire Feb 12 '16 at 21:18
28

Here is an additional answer that was also great help for me to understand how it worked : http://www.javacodegeeks.com/2013/07/spring-bean-and-propertyplaceholderconfigurer.html

any BeanFactoryPostProcessor beans have to be declared with a static, modifier

@Configuration
@PropertySource("classpath:root/test.props")
public class SampleConfig {
 @Value("${test.prop}")
 private String attr;
 @Bean
 public SampleService sampleService() {
  return new SampleService(attr);
 }

 @Bean
 public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
  return new PropertySourcesPlaceholderConfigurer();
 }
}
Michael Técourt
  • 3,457
  • 1
  • 28
  • 45
  • No need to explicitly register `PropertySourcesPlaceholderConfigurer` Bean with `@PropertySource` –  Jan 26 '17 at 21:51
  • @dubey-theHarcourtians which Spring (core) version do you use? if you're using Spring Boot you don't even need `@PropertySource` altogether. – Michael Técourt Jan 27 '17 at 12:05
14

If you need to manually read a properties file without using @Value.

Thanks for the well written page by Lokesh Gupta : Blog

enter image description here

package utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.io.File;


public class Utils {

    private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class.getName());

    public static Properties fetchProperties(){
        Properties properties = new Properties();
        try {
            File file = ResourceUtils.getFile("classpath:application.properties");
            InputStream in = new FileInputStream(file);
            properties.load(in);
        } catch (IOException e) {
            LOGGER.error(e.getMessage());
        }
        return properties;
    }
}
John
  • 2,445
  • 2
  • 17
  • 25
7

Another way is using a ResourceBundle. Basically you get the bundle using its name without the '.properties'

private static final ResourceBundle resource = ResourceBundle.getBundle("config");

And you recover any value using this:

private final String prop = resource.getString("propName");
Miluna
  • 309
  • 3
  • 9
6

You need to put a PropertyPlaceholderConfigurer bean in your application context and set its location property.

See details here : http://www.zparacha.com/how-to-read-properties-file-in-spring/

You might have to modify your property file a bit for this thing to work.

Hope it helps.

instanceOfObject
  • 2,936
  • 5
  • 49
  • 85
2

I wanted an utility class which is not managed by spring, so no spring annotations like @Component, @Configuration etc. But I wanted the class to read from application.properties

I managed to get it working by getting the class to be aware of the Spring Context, hence is aware of Environment, and hence environment.getProperty() works as expected.

To be explicit, I have:

application.properties

mypath=somestring

Utils.java

import org.springframework.core.env.Environment;

// No spring annotations here
public class Utils {
    public String execute(String cmd) {
        // Making the class Spring context aware
        ApplicationContextProvider appContext = new ApplicationContextProvider();
        Environment env = appContext.getApplicationContext().getEnvironment();

        // env.getProperty() works!!!
        System.out.println(env.getProperty("mypath")) 
    }
}

ApplicationContextProvider.java (see Spring get current ApplicationContext)

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ApplicationContextProvider implements ApplicationContextAware {
    private static ApplicationContext CONTEXT;

    public ApplicationContext getApplicationContext() {
        return CONTEXT;
    }

    public void setApplicationContext(ApplicationContext context) throws BeansException {
        CONTEXT = context;
    }

    public static Object getBean(String beanName) {
        return CONTEXT.getBean(beanName);
    }
}
Sida Zhou
  • 3,529
  • 2
  • 33
  • 48
0
 [project structure]: https://i.stack.imgur.com/RAGX3.jpg
-------------------------------
    package beans;

        import java.util.Properties;
        import java.util.Set;

        public class PropertiesBeans {

            private Properties properties;

            public void setProperties(Properties properties) {
                this.properties = properties;
            }

            public void getProperty(){
                Set keys = properties.keySet();
                for (Object key : keys) {
                    System.out.println(key+" : "+properties.getProperty(key.toString()));
                }
            }

        }
    ----------------------------

        package beans;

        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;

        public class Test {

            public static void main(String[] args) {
                // TODO Auto-generated method stub
                ApplicationContext ap = new ClassPathXmlApplicationContext("resource/spring.xml");
                PropertiesBeans p = (PropertiesBeans)ap.getBean("p");
                p.getProperty();
            }

        }
    ----------------------------

 - driver.properties

    Driver = com.mysql.jdbc.Driver
    url = jdbc:mysql://localhost:3306/test
    username = root
    password = root
    ----------------------------



     <beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:util="http://www.springframework.org/schema/util"
               xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

            <bean id="p" class="beans.PropertiesBeans">
                <property name="properties">
                    <util:properties location="classpath:resource/driver.properties"/>
                </property>
            </bean>

        </beans>
Sangram Badi
  • 4,054
  • 9
  • 45
  • 78
0

I'll recommend reading this link https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html from SpringBoot docs about injecting external configs. They didn't only talk about retrieving from a properties file but also YAML and even JSON files. I found it helpful. I hope you do too.

theyCallMeJun
  • 911
  • 1
  • 10
  • 21
0

In Spring Boot version 3; Create a file like this : GlobalProperties.java

package com.tester.trader.config;

import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;



@Component
@ConfigurationProperties
@PropertySource({"classpath:global.properties"})
@Data
@ToString
public class GlobalProperties {
    private String loginUrl;
    private String symbolsUrl;
  

}

Add file global.properties to your resources folder beside the application.properies and paste the following

symbolsUrl=https://api.market-stage.test.com/market/symbol-thumb
loginUrl="https://api.test.com/api/sign-in"

Now you can @Authowired in every service like this:

 @Autowired
 GlobalProperties globalProperties;


public String readIt(){
       return globalProperties.getSymbolsUrl()
}
jdev
  • 5,304
  • 1
  • 17
  • 20