I have these configurations inside spring-mvc-crud-demo-servlet.xml file which I would like to transfer to a Java config class:
<!-- Define Spring MVC view resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- Step 1: Define Database DataSource / connection pool -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/web_User_tracker?useSSL=false&serverTimezone=UTC" />
<property name="user" value="springstudent" />
<property name="password" value="springstudent" />
<!-- these are connection pool properties for C3P0 -->
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxIdleTime" value="30000" />
</bean>
<!-- Step 2: Setup Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="com.luv2code.springdemo.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Step 3: Setup Hibernate transaction manager -->
<bean id="myTransactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Step 4: Enable configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="myTransactionManager" />
<!-- Add support for reading web resources: css, images, js, etc ... -->
<mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>
I have these Java config files:
#Configuration
#EnableWebMvc
#ComponentScan("myappname")
public class DemoAppConfig implements WebMvcConfigurer {
}
public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { DemoAppConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
#Configuration
public class DatabaseConfig {
#Bean
public DriverManagerDataSource getDataSource() {
DriverManagerDataSource bds = new DriverManagerDataSource();
bds.setDriverClassName("org.postgresql.Drive");
bds.setUrl("jdbc:postgresql://localhost:5432/myappname");
bds.setUsername("postgres");
bds.setPassword("mypass");
return bds;
}
}
I'm not sure however how to map properties like minPoolSize or the SessionFactory bean.
I also have this hibernate.cfg.xml file:
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://localhost/myappname</property>
<property name="connection.username">postgres</property>
<property name="connection.password">mypass</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">5</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.PostgreSQL9Dialect</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCachingRegionFactory</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<mapping class="myappname.entity.User"/>
</session-factory>
</hibernate-configuration>
PS I'm using Spring MVC, not Spring Boot. I don't want to use Spring Boot for this project, because I want to understand how to do it with Spring MVC, so please, don't recommend it.
Following is a working code that I used to learn spring - hibernate integration.
You already have the datasource configured and you may modify the code as per your requirement. The transaction and session management is taken care of in this configuration .
package rg.so.poc.txn.config;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
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;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
public class DataConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
//.addScript("data.sql")
.build();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean emFactoryBean = new LocalContainerEntityManagerFactoryBean();
emFactoryBean.setDataSource(dataSource);
emFactoryBean.setPackagesToScan(new String[] { "rg.so.poc.txn.entity" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
emFactoryBean.setJpaVendorAdapter(vendorAdapter);
emFactoryBean.setJpaProperties(hibernateProperties());
return emFactoryBean;
}
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "none");
hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
return hibernateProperties;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
Related
I am fairly new to the Spring Framework and have been having some trouble setting up the project I am currently working on. I need to be able to connect to two different databases one being MongoDB and the other being MSSQL. I am using JPA to connect to the MSSQL.
The problem that I am encountering is that it appears to be trying to make calls to the Mongo database when I want it to make calls to the MSSQL and I'm not really sure how to tell it what to read from. I have seen the posts advising to use the #Qualifier annotation to direct it to the correct implementation, but I don't think that that will work for my case.
#RestController
#RequestMapping("/software")
public class SoftwareEndpoint {
#Autowired
SoftwareRepository repo;
/**********************************************************************************
********************************MSSQL calls****************************************
***********************************************************************************/
#RequestMapping(value="/all",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON)
String getAllSoftware(){
System.out.println("Here1");
List<Software> allSoftware = (List<Software>) repo.findAll();
System.out.println("Here2");
//rest of method and class
Above shows a snippet of my controller class that has an instance of my SoftwareRepository. I also print to the out stream before and after the db call.
The out stream only shows "Here1", goes on to print out this line:
2016-10-04 07:35:39.810 INFO 4236 --- [nio-8080-exec-2] org.mongodb.driver.cluster : No server chosen by ReadPreferenceServerSelector{readPreference=primary} from cluster description ClusterDescription{type=UNKNOWN, connectionMode=SINGLE, all=[ServerDescription{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused: connect}}]}. Waiting for 30000 ms before timing out
and then throws an exception on timeout.
I do not have a mongo instance running locally, however there will be on where the application is being deployed, but I don't believe that this is the problem because on hitting that endpoint, it shouldn't be making a call to the Mongo database, it should be trying to reach out to MSSQL.
TLDR: How do I specify which database implementation for Spring to use for a specific repository or database call?
You can connect to different databases in spring based on the configuration in context.
The below code is for connecting to MySql and Mongo DB. You can substitute MySql with MSSQL provided you have the JDBC for it. Check http://jdbforms.sourceforge.net/UsersGuide/html/ch20s02.html for what the properties for JDBC connection mean.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="mySqldataSource" /> <!-- Change the datasource to MSSQL-->
</bean>
<bean id="mySqldataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="removeAbandoned">
<value>true</value>
</property>
<property name="removeAbandonedTimeout">
<value>30</value>
</property>
<property name="driverClassName">
<value>MSSQL_DRIVER_CLASS_NAME</value>
</property>
<property name="url">
<value>MSSQL_DATABASE_URL</value>
</property>
<property name="username">
<value>MSSQL_DB_USER_NAME</value>
</property>
<property name="password">
<value>MSSQL_DB_PASSWORD</value>
</property>
<property name="maxIdle">
<value>10</value>
</property>
<property name="maxActive">
<value>10</value>
</property>
<property name="maxWait">
<value>100000</value>
</property>
<property name="testOnBorrow">
<value>false</value>
</property>
<property name="testWhileIdle">
<value>false</value>
</property>
<property name="timeBetweenEvictionRunsMillis">
<value>60000</value>
</property>
<property name="minEvictableIdleTimeMillis">
<value>60000</value>
</property>
<property name="numTestsPerEvictionRun">
<value>1</value>
</property>
<property name="defaultTransactionIsolation" value="1" />
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="1" />
</bean>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"></bean>
Below is for connecting to mongodb
<mongo:db-factory dbname="mongoDbName" host="mongoServer" port="mongoPort"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<mongo:repositories base-package="com.test.repoPackage"/> <!-- Package containing the mongo repository interfaces -->
Now you can use the repositories provided by spring.
EDIT 1: Suppose name of config is springConfig.properties. In the above example for the properties dbname, host and port in mongo:db-factory, you would want the values to be configured in springConfig.properties. So lets name them below:
mongoServer = xxx.xx.xxx.xxx
mongoPort = 27017
mongoDb = testDb
Now the context file needs to be modified to import the springConfig.properties. this is done as below in the context file:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<property name="locations" >
<list>
<value>classpath:/log4j.properties</value>
<value>classpath:/springConfig.properties</value>
</list>
</property>
</bean>
The bean mongo:db-factory would now look like:
<mongo:db-factory dbname="${mongoDb}" host="${mongoServer}" port="${mongoPort}"/>
Notice that the "keys" from config (dbname, host and port) are represented insde ${}. This will replace with values in config for the keys.
You need to have two separated config for JPA. Don't forget to disable JPA auto configuration.
#SpringBootApplication(
exclude={
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
}
)
Below is example for two different sql database. Could be easily adapted for your needs (when second datasource is mongo).
First one:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "sellitEntityManagerFactory",
transactionManagerRef = "sellitTransactionManager",
basePackages = { "co.sellit.core.api.repository.sellit" }
)
public class JpaSellitConfig {
#Bean
#ConfigurationProperties(prefix="spring.datasource.sellit")
public DataSourceProperties sellitDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties(prefix="spring.hikaricp.sellit")
public HikariConfig sellitHikariConfig() {
HikariConfig hikariConfig = new HikariConfig();
return hikariConfig;
}
#Bean
public DataSource sellitDataSource(
#Qualifier("sellitHikariConfig") HikariConfig sellitHikariConfig,
#Qualifier("sellitDataSourceProperties") DataSourceProperties sellitDataSourceProperties) {
sellitHikariConfig.setDriverClassName(sellitDataSourceProperties.getDriverClassName());
sellitHikariConfig.setJdbcUrl(sellitDataSourceProperties.getUrl());
sellitHikariConfig.setUsername(sellitDataSourceProperties.getUsername());
sellitHikariConfig.setPassword(sellitDataSourceProperties.getPassword());
sellitHikariConfig.setConnectionTestQuery("SELECT 1");
HikariDataSource hikariDataSource = new HikariDataSource(sellitHikariConfig);
return hikariDataSource;
}
#Bean
#ConfigurationProperties(prefix="spring.jpa.sellit")
public JpaVendorAdapter sellitJpaVendorAdapter() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
return jpaVendorAdapter;
}
#Bean
#Autowired
public EntityManagerFactory sellitEntityManagerFactory(
#Qualifier("sellitDataSource") DataSource sellitDataSource,
#Qualifier("sellitJpaVendorAdapter") JpaVendorAdapter sellitJpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean lemf = new LocalContainerEntityManagerFactoryBean();
lemf.setDataSource(sellitDataSource);
lemf.setJpaVendorAdapter(sellitJpaVendorAdapter);
lemf.setPackagesToScan("co.sellit.core.api.entity.sellit");
lemf.setPersistenceUnitName("sellitPersistenceUnit");
lemf.afterPropertiesSet();
return lemf.getObject();
}
#Bean
#Autowired
public EntityManager sellitDataSourceEntityManager(
#Qualifier("sellitEntityManagerFactory") EntityManagerFactory sellitEntityManagerFactory) {
return sellitEntityManagerFactory.createEntityManager();
}
#Bean
#Autowired
#Qualifier("sellitTransactionManager")
public PlatformTransactionManager sellitTransactionManager(
#Qualifier("sellitEntityManagerFactory") EntityManagerFactory sellitEntityManagerFactory) {
return new JpaTransactionManager(sellitEntityManagerFactory);
}
}
Second one:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "ofEntityManagerFactory",
transactionManagerRef = "ofTransactionManager",
basePackages = { "co.sellit.core.api.repository.openfire" }
)
public class JpaOpenfireConfig {
#Bean
#ConfigurationProperties(prefix="spring.datasource.openfire")
public DataSourceProperties ofDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties(prefix="spring.hikaricp.openfire")
public HikariConfig ofHikariConfig() {
HikariConfig hikariConfig = new HikariConfig();
return hikariConfig;
}
#Bean
public DataSource ofDataSource(
#Qualifier("ofHikariConfig") HikariConfig ofHikariConfig,
#Qualifier("ofDataSourceProperties") DataSourceProperties ofDataSourceProperties) {
ofHikariConfig.setDriverClassName(ofDataSourceProperties.getDriverClassName());
ofHikariConfig.setJdbcUrl(ofDataSourceProperties.getUrl());
ofHikariConfig.setUsername(ofDataSourceProperties.getUsername());
ofHikariConfig.setPassword(ofDataSourceProperties.getPassword());
ofHikariConfig.setConnectionTestQuery("SELECT 1");
HikariDataSource hikariDataSource = new HikariDataSource(ofHikariConfig);
return hikariDataSource;
}
#Bean
#ConfigurationProperties(prefix="spring.jpa.openfire")
public JpaVendorAdapter ofJpaVendorAdapter() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
return jpaVendorAdapter;
}
#Bean
#Autowired
public EntityManagerFactory ofEntityManagerFactory(
#Qualifier("ofDataSource") DataSource ofDataSource,
#Qualifier("ofJpaVendorAdapter") JpaVendorAdapter ofJpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean lemf = new LocalContainerEntityManagerFactoryBean();
lemf.setDataSource(ofDataSource);
lemf.setJpaVendorAdapter(ofJpaVendorAdapter);
lemf.setPackagesToScan("co.sellit.core.api.entity.openfire");
lemf.setPersistenceUnitName("ofPersistenceUnit");
lemf.afterPropertiesSet();
return lemf.getObject();
}
#Bean
#Autowired
public EntityManager ofDataSourceEntityManager(
#Qualifier("ofEntityManagerFactory") EntityManagerFactory ofEntityManagerFactory) {
return ofEntityManagerFactory.createEntityManager();
}
#Bean
#Autowired
#Qualifier("ofTransactionManager")
public PlatformTransactionManager ofTransactionManager(
#Qualifier("ofEntityManagerFactory") EntityManagerFactory ofEntityManagerFactory) {
return new JpaTransactionManager(ofEntityManagerFactory);
}
}
So repositories from package co.sellit.core.api.repository.sellit will use sellit db
But repositories from package co.sellit.core.api.repository.openfire will use openfire database.
UPDATE (xml config version)
<bean id="openfireDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/openfire?characterEncoding=UTF-8" />
</bean>
<bean id="sellitDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/sellit?characterEncoding=UTF-8" />
</bean>
<bean id="openfireSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="openfireDataSource" />
<property name="packagesToScan" value="co.sellit.core.api.repository.openfire" />
<property name="hibernateProperties">
<props>
...
</props>
</property>
</bean>
<bean id="sellitSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="sellitDataSource" />
<property name="packagesToScan" value="co.sellit.core.api.repository.sellit" />
<property name="hibernateProperties">
<props>
...
</props>
</property>
</bean>
<bean id="openfireTxnManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="openfireSessionFactory" />
</bean>
<bean id="sellitTxnManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sellitSessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="openfireTxnManager" />
<tx:annotation-driven transaction-manager="sellitTxnManager" />
I'm trying to setup a Tomcat connection pool (to MySQL) in my Java web app, while using the Spring JDBCTemplate.
This is the Java class to create the connection pool:
#Configuration
public class DataAccessConfiguration {
#Bean(destroyMethod = "close")
public javax.sql.DataSource datasource() {
org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource();
ds.setDriverClassName("org.h2.Driver");
ds.setUrl("jdbc:h2:java-config");
ds.setUsername("sa");
ds.setPassword("");
ds.setInitialSize(5);
ds.setMaxActive(10);
ds.setMaxIdle(5);
ds.setMinIdle(2);
return ds;
}
#Bean public JdbcOperations tpl() {
return new JdbcTemplate(datasource());
}
}
This is how I get the ApplicationContext (in the main method for example):
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
How should I define the DataAccessConfiguration class in the Beans.xml file so Spring knows to use it?
**
Update:
**
This is the actual configuration method:
public javax.sql.DataSource datasource() {
org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource();
PoolProperties p = new PoolProperties();
p.setUrl("jdbc:mysql://localhost:3306/mysql");
p.setDriverClassName("com.mysql.jdbc.Driver");
p.setUsername("root");
p.setPassword("");
p.setJmxEnabled(true);
p.setTestWhileIdle(false);
p.setTestOnBorrow(true);
p.setValidationQuery("SELECT 1");
p.setTestOnReturn(false);
p.setValidationInterval(30000);
p.setTimeBetweenEvictionRunsMillis(30000);
p.setMaxActive(100);
p.setInitialSize(10);
p.setMaxWait(10000);
p.setRemoveAbandonedTimeout(60);
p.setMinEvictableIdleTimeMillis(30000);
p.setMinIdle(10);
p.setLogAbandoned(true);
p.setRemoveAbandoned(true);
p.setJdbcInterceptors(
"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
"org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
ds.setPoolProperties(p);
return ds;
}
Can you please help rewrite in the Beans.xml?
For the values passed in Properties setter methods exist. Therefore XML-based bean definition goes like:
<bean name="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<property name="url" value="jdbc:mysql://localhost:3306/mysql"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
....
</bean>
<bean name="tpl" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="jdbcUrl" value="#{config['db.url']}" />
<property name="driverClass" value="#{config['db.driver']}" />
<property name="user" value="#{config['db.username']}" />
<property name="password" value="#{config['db.password']}" />
<property name="acquireIncrement" value="1" />
<property name="idleConnectionTestPeriod" value="300" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="20" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
I am using spring framework and for database I am using hibernate.cfg.xml in the following way
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="show_sql">false</property>
<property name="hbm2ddl.auto">update</property>
<mapping class="com.lynas.test.Student" />
</session-factory>
</hibernate-configuration>
Now is there any way to write this code in the java file. Like a bean or something??
The Answer is YES. from http://java.dzone.com/articles/springhibernate-application
package com.sivalabs.springmvc.config;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
import org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;
/**
* #author SivaLabs
*
*/
#Configuration
public class RepositoryConfig
{
//${jdbc.driverClassName}
#Value("${jdbc.driverClassName}") private String driverClassName;
#Value("${jdbc.url}") private String url;
#Value("${jdbc.username}") private String username;
#Value("${jdbc.password}") private String password;
#Value("${hibernate.dialect}") private String hibernateDialect;
#Value("${hibernate.show_sql}") private String hibernateShowSql;
#Value("${hibernate.hbm2ddl.auto}") private String hibernateHbm2ddlAuto;
#Bean()
public DataSource getDataSource()
{
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(driverClassName);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory)
{
HibernateTransactionManager htm = new HibernateTransactionManager();
htm.setSessionFactory(sessionFactory);
return htm;
}
#Bean
#Autowired
public HibernateTemplate getHibernateTemplate(SessionFactory sessionFactory)
{
HibernateTemplate hibernateTemplate = new HibernateTemplate(sessionFactory);
return hibernateTemplate;
}
#Bean
public AnnotationSessionFactoryBean getSessionFactory()
{
AnnotationSessionFactoryBean asfb = new AnnotationSessionFactoryBean();
asfb.setDataSource(getDataSource());
asfb.setHibernateProperties(getHibernateProperties());
asfb.setPackagesToScan(new String[]{"com.sivalabs"});
return asfb;
}
#Bean
public Properties getHibernateProperties()
{
Properties properties = new Properties();
properties.put("hibernate.dialect", hibernateDialect);
properties.put("hibernate.show_sql", hibernateShowSql);
properties.put("hibernate.hbm2ddl.auto", hibernateHbm2ddlAuto);
return properties;
}
}
A more modern, working solution:
#Configuration
#ComponentScan(basePackageClasses = {массив пакетов с классами #Component, #Service, #Repository, #Controller})
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "com.jdev.blog.admin.crud.repositories", entityManagerFactoryRef = "entityManagerFactory")
public class ApplicationConfiguration {
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setJpaProperties(hibProperties());
return entityManagerFactoryBean;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
return properties;
}
#Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
NO the above database configration cannot be moved to a java file BUT can be moved to dispactcher servelet.Actually that whole hibernate.cfg.xml is not required from spring 2.5 version upwards.
You can do the set up of the hibernate properties inside the dispatcher servlet like this. The below code uses mysql dialect so replace it with your requirement also replace name of the database,username and password of the database.
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">
<context:component-scan base-package="com.c.controllers" />
<context:component-scan base-package="com.c.service" />
<context:component-scan base-package="com.c.dao" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/"your database name"</value>
</property>
<property name="username">
<value>"insert username here"</value>
</property>
<property name="password">
<value>"insert password here"</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="myDataSource" />
</property>
<property name="annotatedClasses">
<list>
<value>com.c.beans.Employee</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
I am switching from XML to Java based Spring configuration. Following is my xml configuration to setup and initialize my H2 database.
<beans profile="test-h2">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:target/h2/pps;AUTO_SERVER=TRUE"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="entityManagerFactory" parent="entityManagerFactoryCommonParent">
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
</beans>
Following is my java based configuration to setup my H2 database in Server Mode.
private static final String H2_JDBC_URL_TEMPLATE = "jdbc:h2:%s/db/merchant;AUTO_SERVER=TRUE";
private DataSource createH2DataSource() {
String jdbcUrl = String.format(H2_JDBC_URL_TEMPLATE, System.getProperty("user.home"));
JdbcDataSource ds = new JdbcDataSource();
ds.setURL(jdbcUrl);
ds.setUser("sa");
ds.setPassword("");
return ds;
}
How can I run scripts to initialize schema and add in some test data? Any ideas?
I have found a way to do it.
#Value("classpath:seed-data.sql")
private Resource H2_SCHEMA_SCRIPT;
#Value("classpath:test-data.sql")
private Resource H2_DATA_SCRIPT;
#Value("classpath:drop-data.sql")
private Resource H2_CLEANER_SCRIPT;
#Bean
public DataSource dataSource(Environment env) throws Exception {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
}
#Autowired
#Bean
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
final DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
initializer.setDatabasePopulator(databasePopulator());
return initializer;
}
private DatabasePopulator databasePopulator() {
final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.addScript(H2_SCHEMA_SCRIPT);
populator.addScript(H2_DATA_SCRIPT);
return populator;
}
I've inherited a Spring 3 app that uses XML files to define and wire together the beans. I know that since Spring 2 these can mostly be replaced with annotations. I would like Spring to:
detect beans by scanning certain packages for classes with whatever annotation is used to indicate a Spring bean
attempt to autowire-by-name and field in a bean that I have marked with the relevant annotation
What are steps I need to take to make this happen?
The manual has all the info you need: http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/beans.html#beans-annotation-config
The TL;DR version is that you need to add <context:annotation-config/> to your spring config and then annotate your beans with #Component and in your setter of properties annotate with #Autowired
I shall give you a xml configuration with it anotation based config equivalent respectively, so that you will easily see how to change your bean from xml to java and vice-versa
`<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="com.mycompany.backendhibernatejpa.controller" />
<mvc:annotation-driven />
<bean id="iAbonneDao" class="com.mycompany.backendhibernatejpa.daoImpl.AbonneDaoImpl"/>
<bean id="iAbonneService" class="com.mycompany.backendhibernatejpa.serviceImpl.AbonneServiceImpl"/>
<!-- couche de persistance JPA -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="generateDdl" value="true" />
<property name="showSql" value="true" />
</bean>
</property>
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:bd.properties"/>
</bean>
<!-- la source de donnéees DBCP -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
<property name="driverClassName" value="${bd.driver}" />
<property name="url" value="${bd.url}" />
<property name="username" value="${bd.username}" />
<property name="password" value="${bd.password}" />
</bean>
<!-- le gestionnaire de transactions -->
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- traduction des exceptions -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<!-- annotations de persistance -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>`
this file is named springrest-sevlet. actually you can give the name
you want followed by "-servlet" and mention that name in the file
web.xml
` <web-app>
<display-name>Gescable</display-name>
<servlet>
<servlet-name>springrest</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springrest</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>`
the two files should be place in the folder "WEB-INF".
Now the equivalent with anotation based config
`/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.mycompany.backendhibernatejpaannotation.configuration;
import com.mycompany.backendhibernatejpaannotation.daoImpl.AbonneDaoImpl;
import com.mycompany.backendhibernatejpaannotation.daoInterface.IAbonneDao;
import com.mycompany.backendhibernatejpaannotation.serviceImpl.AbonneServiceImpl;
import com.mycompany.backendhibernatejpaannotation.serviceInterface.IAbonneService;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
*
* #author vivien saa
*/
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.mycompany.backendhibernatejpaannotation")
public class RestConfiguration {
#Bean
public IAbonneDao iAbonneDao() {
return new AbonneDaoImpl();
}
#Bean
public IAbonneService iAbonneService() {
return new AbonneServiceImpl();
}
// #Bean
// public PropertyPlaceholderConfigurer placeholderConfigurer() {
// PropertyPlaceholderConfigurer placeholderConfigurer = new PropertyPlaceholderConfigurer();
// placeholderConfigurer.setLocations("classpath:bd.properties");
// return placeholderConfigurer;
// }
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/gescable");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
#Bean
public HibernateJpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect");
jpaVendorAdapter.setGenerateDdl(true);
jpaVendorAdapter.setShowSql(true);
return jpaVendorAdapter;
}
#Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource());
entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter());
entityManagerFactory.setLoadTimeWeaver(loadTimeWeaver());
return entityManagerFactory;
}
#Bean
public JpaTransactionManager jpaTransactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return jpaTransactionManager;
}
#Bean
public PersistenceExceptionTranslationPostPro`enter code here`cessor persistenceExceptionTranslationPostProcessor() {
return new PersistenceExceptionTranslationPostProcessor();
}
#Bean
public PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {
return new PersistenceAnnotationBeanPostProcessor();
}
}`
this file must be accompanied by this one
`
package com.mycompany.backendhibernatejpaannotation.configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
*
* #author vivien saa
*/
public class Initializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RestConfiguration.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
`
I think the first thing to do is to go slow. Just pick one service at a time and migrate it as you have cause to touch it. Mucking with a ton of spring config is a sure way screw yourself in production with a dependency you only need once in a while.