Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC, how to read and access application.properties?

I am working on an application with Spring MVC (and Hibernate) and feel a bit confused about configuration issues. It does not make it simpler that there are so many ways of setting up and configuring Spring application, which are sometimes even mixed throughout tutorials...

I use Spring 4 with a pure Java-based configuration, so free of XML configuration files. The entry point for the application is a subclass of AbstractAnnotationConfigDispatcherServletInitializer:

public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class[] {
            HibernateConfig.class, 
            ServiceConfig.class };
}

@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class[] {MvcConfig.class};
}

@Override
protected String[] getServletMappings() {
    return new String[] {"/"};
}
}

We see that there are 2 root configuration classes, for loading the Hibernate and the Service config classes respectively, and one for loading the Service config class (which actually does nothing more than scanning for conponents under the ~.service package).

The HibernateConfig is the only one which needs properties from the application.properties file, so this file is read as a PropertySource and used in the class as follows:

package nl.drsklaus.activiteitensite.configuration;

//imports

@Configuration
@EnableTransactionManagement
@ComponentScan({"nl.mydomain.activiteitensite.dao"})
@PropertySource(value= {"classpath:application.properties"})
public class HibernateConfig {

@Autowired
private Environment environment;

@Bean
public LocalSessionFactoryBean sessionFactory() {
  //code
  return sessionFactory;
}

@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
    dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
    dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
    dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));

    return dataSource;
}

@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(s);
    return txManager;
}

private Properties hibernateProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
    properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
    //TODO connection pooling configuration

    return properties;
}
}

As we see, the properties are used in the configuration file containing the @PropertySource annotation. But it is very well possible that also other configuration files will need to accesss application.properties. And moreover, I plan to define more properties in this file, for example the directory where user images will be stored. This information will be needed in Controller methods, so I need to have a more global way of acceessing application.properties.

So my questions are:

  • Does the injected Environment only give access to the property file if the @PropertyResource is defined in the very same configuration class?
  • When more than one @Configuration classes need access to application.properties, do we need to add the @PropertyResources to all of them (forcing us to repeat the name of the property file)
  • How can we access the property file from the Controller classes without loading it explicitly, repeating its name?

In the future, there will possibly multiple versions of the property file for testing and live deployment.

like image 970
klausch Avatar asked Feb 22 '16 11:02

klausch


People also ask

How do I view application properties in spring?

Another way to read application properties in the Spring Boot application is to use the @ConfigurationProperties annotation. To do that, we will need to create a Plain Old Java Object where each class field matches the name of the key in a property file.

How read properties file in spring MVC?

Spring framework gives us two annotation @PropertySource and @Value which make the reading properties file values super easy. @PropertySource annotation is used to define the properties file location and @Value annotation is used to inject the properties file values into the bean.

Where is application properties in spring MVC?

Spring Boot Framework comes has a built-in mechanism for application configuration using a file called the 'application. properties'. It is located in the src/main/resources folder, as shown below in the following figure. The Spring Boot framework provides various properties that can be configured in the 'application.


1 Answers

In order of questions:

  • No. @PropertyResource added to you configuration gives you access to this property file from any bean of application. Before beans creation, Spring collects all property sources of all configurations, and puts it into single Environment of Application context.
  • No, we don't need to add the @PropertyResources to all of them. You can add property source to one configuration and use it in the another one. So, you don't need to repeat name of the property file. Declare it once, and use anywhere.
  • As you guessed in controllers it works as well as in other beans. You need just declare @PropertyResources in config, add this config to you context, and use properties in controller. Of cause, you can autowire Environment, as you did in your example, and get properties from it. But in my opinion using of @Value annotation little bit more convenient:

    @Configuration
    @PropertySource(value= {"classpath:application.properties"})
    public class MyConfig{
    
        //spring will automatically bind value of property
        @Value("${my.property}")
        private String myProperty;
    
        //this bean needed to resolve ${property.name} syntax
        @Bean
        public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
            return new PropertySourcesPlaceholderConfigurer();
        }
    }
    

Same way in controllers:

    @Controller
    public class MyController{

        //spring will automatically bind value of property
        @Value("${my.property}")
        private String myProperty;

        @RequestMapping("/mapping")
        public String controllerMethod(){
             ...
        }
    }
like image 195
Ken Bekov Avatar answered Oct 05 '22 10:10

Ken Bekov