I am working on a Spring-MVC application in which we are preparing to setup application on different servers. As each server can have it's own database related configuration, we are hoping to use an external properties file(outside the war file) which can be read while project is starting. How do I go about this approach? For making it work, I have already moved application initialization code to Java, this way, static XML reading which we had before won't be required. But, we are unsure how to create and add a properties file dynamically which atleast has these 3 values(JDBC URL containing DB name, username, password). All tables, other data will be created automatically.
Here is the class where app is initialized :
WebConfig.java :
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.ourapp.spring"})
@EnableTransactionManagement
@EnableCaching
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
@Bean
public ReloadableResourceBundleMessageSource messageSource(){
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("../resources/locale/messages.properties");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocaleChangeInterceptor localeInterceptor(){
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang");
return interceptor;
}
@Bean
public MappingJackson2HttpMessageConverter converter() {
return new MappingJackson2HttpMessageConverter();
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/img/**").addResourceLocations("/img/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
}
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("../webapp/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
@Bean
public DoNotTruncateMyUrls doNotTruncate(){
return new DoNotTruncateMyUrls();
}
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
@Bean
@Qualifier("primary_tx")
public HibernateTransactionManager getPrimaryTransactionManager() throws IOException {
HibernateTransactionManager txName= new HibernateTransactionManager();
txName.setSessionFactory(sessionFactory().getObject());
return txName;
}
@Bean
@Qualifier("extended_tx")
public HibernateTransactionManager txName() throws IOException {
HibernateTransactionManager txName= new HibernateTransactionManager();
txName.setSessionFactory(getExtendedSessionFactory().getObject());
return txName;
}
@Bean
@Qualifier("sessionFactory_origin")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(new DataSourceConfig().primaryDataSource());
sessionFactory.setPackagesToScan("com.ourapp.spring");
return sessionFactory;
}
@Bean
@Qualifier("sessionFactory_extended")
public LocalSessionFactoryBean getExtendedSessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(new DataSourceConfig_Extended().secondaryDataSource());
sessionFactory.setPackagesToScan("com.ourapp.spring");
return sessionFactory;
}
}
Thank you. :-)
You can do this using
PropertySourcesPlaceholderConfigurer
Create a bean like this
For example if you write file:/tmp/dev/*.properties . It will load all the properties file under /tmp/dev.
If you want to customize it based on differnt environment(dev, testing, production). then you can use
@Profile
and create multiple beans.Probably what you are looking for is Profiles(
@Profile or @Conditional
)Step1: Create a profile. The following is the example for prod profile. Similarly, you can create one for
dev
andqa
Step2 Activate profiles
UPDATE
Use
PropertyConfigurator.configure(Loader.getResource(<your-file-path>));
if the file is located outside the packaged war. Later you can simply inject values using@Value or SPel
Write a config manager, which will create configuration objects based on the name of properties file. For example,
Configuration config = ConfigurationManager.getConfig("dbConfig");
so, now your config object will contain all properties related to db. When you instantiate config object read all properties into this object.
Let's say your properties file contains following fields:
user.name = "Tom" user.password = "pass"
Next time when you need "user.name", you would just do
config.getString("user.name")