M314
M314

Reputation: 955

Proper way to handle properties files in spring code base configuration

I am started writing application where I wanted to include as much spring configuration in java code as I can. The problem that I encounter is with properties file. Take a look what I have writen so far:

File containing beans declaration:

@Configuration
@ImportResource("classpath:properties-configuration.xml")
public class ContextConfigutarion {

    @Value("${database.url}")
    private String database_url;

    @Value("${database.user}")
    private String database_user;

    @Value("${database.password}")
    private String database_password;

    @Value("${database.default.shema}")
    private String database_default_shema;

    @Bean
    public BasicDataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
        dataSource.setUrl(database_url);
        dataSource.setUsername(database_user);
        dataSource.setPassword(database_password);
        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setHibernateProperties(hibernateProperties);  // <- here I encountered a problem 
        return sessionFactory;
    }
...
}

properties-configuration.xml it is minimum necessery file, used only for specify file properties location:

<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context.xsd">

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

</beans>   

When I started configuring sessionFactory object I notice a problem. As I understand in ContextConfiguration class I have to subtract every property from my database.properties file. If my application have a lot of properties then my configuration java code is redundantly growing. Isn't there better way to transfer properties through Spring to my components without extracting every single one of them.

Second related question: what is there a good way to preserve application properties in tree like structure? Because as you see in above example application properties contain: data source properties, hibernate properties, etc. which in fact is property tree. If my application whould be bigger and have more components preserving properies in tree like structure whould be great. I image that I have properties stored in catalogs like that:

/application
    /hibernate
        filename.properties
    /database
        filename.properties
    /someOddComponent
        /someStrangeComponent
            filename.properties
        filename.properties
    filename.properties

So if I ask for application.properties I whould got sum for all .properties files in application directory (and sub catalogs), if I ask for hibernate.properties I whould got sum for all .properties files hibernate directory (and sub catalogs), etc. Maybe here I exaggerate the problem, what do you think?

Upvotes: 0

Views: 2085

Answers (1)

M. Deinum
M. Deinum

Reputation: 125232

First ditch your xml file and use a @PropertySource annotation to load the properties file and register a PropertySourcePlaceholderConfigurer in your configuration class.

@Configuration
@PropertySource("classpath:database.properties")
public class ContextConfigutarion {

    @Bean
    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer ();
    }
}

If you have a lot of properties instead of specifying @Value annotations use the Environment and the getProperty and getRequiredProperty methods instead.

@Configuration
@PropertySource("classpath:database.properties")
public class ContextConfigutarion {

    @Autowired
    private Environment env;

    @Bean
    public BasicDataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
        dataSource.setUrl(env.getRequiredProperty("database.url"));
        dataSource.setUsername(env.getRequiredProperty("database.user));
        // Other properties
        return dataSource;
    }

}

You don't want to have a lot of configuration files as that will only make things complex and unmaintainable. Limit them to a certain number. If you want a tree like system don't use a property file use a yaml file instead. Although a bit harder too load (not supported by @PropertySource) this allows for tree like configuration structures in a single file.

Or even better let Spring Boot handle the complexity for you (that supports both properties and yaml files out of the box). Reduces your configuration and gives you nice auto config out-of-the-box.

Upvotes: 1

Related Questions