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:
In the future, there will possibly multiple versions of the property file for testing and live deployment.
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.
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.
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.
In order of questions:
@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.@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(){
...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With