Spring MVC 4.x @Profile, Datasource configuration, Hibernate 5.x JPA configurations
Moving an application from one environment to the other can be messy. If I want to put the application in production for instance, I need to change a few settings because my development environment does not use the same settings values. Some settings are also useful for development and not appropriate for production, like the logging level. In my case, I also have base upload paths that vary from one instance to the other.
I have a Spring MVC 4.2.1 application that has a jdbc datasource to a mysql database. I use hibernate 5.0.1 as the JPA provider.
To avoid having to change over and over the settings from one environment to the other, I use application properties files and profiles configuration files. The properties file has the settings for the environment while the configuration file will be referring to the properties values.
I have two java classes, one for dev and one for prod. Both are declared with the @Configuration and @Profile annotations. The first indicates that the class is to be considered as a configuration file while the second makes it a profile. The profile annotation has the name of the profile that will be used later on to make it active in web.xml in the form of @Profile(“profile_name”). Each configuration profile has a corresponding application properties file that has the right values for the concerned setting. The properties file is declared through the annotation @PropertySource. Below is my Production profile class:
package com.elevysi.site.profile; import java.util.Properties; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.orm.hibernate5.HibernateTransactionManager; import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; @Profile("prod") @Configuration @PropertySource("classpath:META-INF/application-prod.properties") public class ProductionProfile { @Autowired private Environment environment; @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); em.setPackagesToScan(new String[] { "com.elevysi.site.entity" }); JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); em.setJpaProperties(hibernateProperties()); return em; } @Bean public DataSource dataSource(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(environment.getRequiredProperty("db.driver")); dataSource.setUrl(environment.getRequiredProperty("db.url")); dataSource.setUsername(environment.getRequiredProperty("db.username")); dataSource.setPassword(environment.getRequiredProperty("db.password")); return dataSource; } private Properties hibernateProperties() { Properties properties = new Properties(); properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect")); properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql")); properties.put("hibernate.max_fetch_depth", environment.getRequiredProperty("hibernate.max_fetch_depth")); properties.put("hibernate.fetch_size", environment.getRequiredProperty("hibernate.fetch_size")); properties.put("hibernate.batch_size", environment.getRequiredProperty("hibernate.batch_size")); return properties; } @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory emf){ JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(emf); return transactionManager; } }
Note that the Dev profile class has exactly the same details as the production one except for the @PropertySource and the @Profile(profile_name)
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; @Profile("dev") @Configuration @PropertySource("classpath:META-INF/application-dev.properties") public class DevelopmentProfile {
Both properties files will enclose the same properties with different values:
#DB properties: db.driver=com.mysql.jdbc.Driver db.url=jdbc:mysql://localhost:3306/db_name db.username=your_sql_username db.password=ypur_sql_password #Hibernate Configuration: hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect hibernate.show_sql=false hibernate.max_fetch_depth=3 hibernate.fetch_size=50 hibernate.batch_size=10 entitymanager.packages.to.scan=com.elevysi.site.entity
To recap, I have two configuration profiles:
• ProductionProfile using application-dev.properties
• DevelopmentProfile using application-prod.properties
To make one or several profiles active, refer to your web.xml and add the following:
<context-param> <param-name>spring.profiles.active</param-name> <param-value>dev</param-value> </context-param>
In the above code, adapt the active profile by changing the <param-value> to the profile name.
- Tags: Technology
- Folders : Spring MVC Persistence - Databases Spring Persistence - Hibernate
- Posted 25 August 2016