How to read values from properties file?
Asked Answered
P

11

148

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?

Parette answered 13/2, 2012 at 11:38 Comment(4)
This does not look like a properties file.Westbrooks
If it is a properties file in the Java sense - yes. Otherwise it is a custom file format that needs to be treated different (and you can't just use the lines as property values in Spring if they don't have a key).Bouleversement
"Not in traditional way" - what do you mean by this?Bouleversement
i mean using annotations..not by xml configuration...Parette
S
210

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
  }
}
Slim answered 13/2, 2012 at 12:37 Comment(7)
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!Parette
Edited as suggested by @Ethan. Thanks for update, could not accept original edit, it was too late already.Slim
For the case where you are dealing with comma separated values perhaps consider what is being proposed here by using EL: #12576656Burkett
@user36123 Yea, that should work too but I think it's more readable to have an array and avoid calcuations in EL.Slim
How do we use aaa? Is it @Value(${aaa}) private String aaa; then we can System.out.println(aaa)???????Mass
@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.Slim
do i have to do it like this? is there a way like int prop = Environment.getProperty("prop.defined.in.the.file");Slaveholder
J
58

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");
    }
}
Jerrelljerri answered 26/1, 2017 at 21:26 Comment(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");Claussen
A
50

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;
   }
}
Abjuration answered 17/4, 2013 at 13:36 Comment(3)
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?Ardra
@KevinMeredith yes, you can, just split your spring configuration by Profile annotation #12692312Abjuration
@KevinMeredith we use a folder outside deploy war: like c:\apps\sys_name\conf\app.properties . Deployment process gets simplified and less error-prone.Gezira
C
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();
 }
}
Coreencorel answered 21/8, 2013 at 7:29 Comment(2)
No need to explicitly register PropertySourcesPlaceholderConfigurer Bean with @PropertySourceJerrelljerri
@dubey-theHarcourtians which Spring (core) version do you use? if you're using Spring Boot you don't even need @PropertySource altogether.Agile
J
15

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;
    }
}
Janettjanetta answered 24/3, 2018 at 18:32 Comment(1)
Thanks, it works for my case. I needs to read the properties from static function.Brachium
P
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");
Plaintive answered 15/11, 2018 at 17:5 Comment(0)
B
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.

Berna answered 13/2, 2012 at 11:41 Comment(0)
B
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);
    }
}
Burial answered 4/12, 2019 at 12:6 Comment(1)
Is this a spring boot project? I try it in my spring project without luck.Crosby
U
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>
Uppish answered 26/8, 2016 at 7:1 Comment(2)
add some explanationGenro
using core container you can't access outside resource properties file, so you need to use j2ee container like ApplicationContext, and you need to use beans level validation like xmlns, xmlns:util, xsi:schemaLocation, xmlns:xsiUppish
C
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.

Chicory answered 3/4, 2018 at 6:34 Comment(0)
C
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()
}
Contrite answered 1/5, 2023 at 11:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.